├── .editorconfig ├── .gitignore ├── .idea └── vcs.xml ├── AUTHORS ├── LICENSE ├── Makefile ├── abc-cli ├── abc-watcher ├── abcd ├── AccountPaths.hpp ├── Context.cpp ├── Context.hpp ├── Export.cpp ├── Export.hpp ├── General.cpp ├── General.hpp ├── RootPaths.cpp ├── RootPaths.hpp ├── WalletPaths.hpp ├── account │ ├── Account.cpp │ ├── Account.hpp │ ├── AccountCategories.cpp │ ├── AccountCategories.hpp │ ├── AccountSettings.cpp │ ├── AccountSettings.hpp │ ├── PluginData.cpp │ ├── PluginData.hpp │ ├── WalletList.cpp │ └── WalletList.hpp ├── bitcoin │ ├── Testnet.cpp │ ├── Testnet.hpp │ ├── Text.cpp │ ├── Text.hpp │ ├── Typedefs.hpp │ ├── Utility.cpp │ ├── Utility.hpp │ ├── Watcher.cpp │ ├── Watcher.hpp │ ├── WatcherBridge.cpp │ ├── WatcherBridge.hpp │ ├── cache │ │ ├── AddressCache.cpp │ │ ├── AddressCache.hpp │ │ ├── BlockCache.cpp │ │ ├── BlockCache.hpp │ │ ├── Cache.cpp │ │ ├── Cache.hpp │ │ ├── ServerCache.cpp │ │ ├── ServerCache.hpp │ │ ├── TxCache.cpp │ │ └── TxCache.hpp │ ├── network │ │ ├── IBitcoinConnection.hpp │ │ ├── LibbitcoinConnection.cpp │ │ ├── LibbitcoinConnection.hpp │ │ ├── StratumConnection.cpp │ │ ├── StratumConnection.hpp │ │ ├── TcpConnection.cpp │ │ ├── TcpConnection.hpp │ │ ├── TxUpdater.cpp │ │ └── TxUpdater.hpp │ └── spend │ │ ├── AirbitzFee.cpp │ │ ├── AirbitzFee.hpp │ │ ├── Broadcast.cpp │ │ ├── Broadcast.hpp │ │ ├── Inputs.cpp │ │ ├── Inputs.hpp │ │ ├── Outputs.cpp │ │ ├── Outputs.hpp │ │ ├── PaymentProto.cpp │ │ ├── PaymentProto.hpp │ │ ├── Spend.cpp │ │ ├── Spend.hpp │ │ ├── Sweep.cpp │ │ ├── Sweep.hpp │ │ └── paymentrequest.proto ├── crypto │ ├── Crypto.cpp │ ├── Crypto.hpp │ ├── Encoding.cpp │ ├── Encoding.hpp │ ├── OtpKey.cpp │ ├── OtpKey.hpp │ ├── Random.cpp │ ├── Random.hpp │ ├── Scrypt.cpp │ └── Scrypt.hpp ├── exchange │ ├── Currency.cpp │ ├── Currency.hpp │ ├── ExchangeCache.cpp │ ├── ExchangeCache.hpp │ ├── ExchangeSource.cpp │ └── ExchangeSource.hpp ├── http │ ├── Http.cpp │ ├── Http.hpp │ ├── HttpRequest.cpp │ ├── HttpRequest.hpp │ ├── Uri.cpp │ └── Uri.hpp ├── json │ ├── JsonArray.cpp │ ├── JsonArray.hpp │ ├── JsonBox.cpp │ ├── JsonBox.hpp │ ├── JsonObject.cpp │ ├── JsonObject.hpp │ ├── JsonPtr.cpp │ ├── JsonPtr.hpp │ ├── JsonSnrp.cpp │ └── JsonSnrp.hpp ├── login │ ├── Bitid.cpp │ ├── Bitid.hpp │ ├── Login.cpp │ ├── Login.hpp │ ├── LoginPassword.cpp │ ├── LoginPassword.hpp │ ├── LoginPin.cpp │ ├── LoginPin.hpp │ ├── LoginPin2.cpp │ ├── LoginPin2.hpp │ ├── LoginRecovery.cpp │ ├── LoginRecovery.hpp │ ├── LoginRecovery2.cpp │ ├── LoginRecovery2.hpp │ ├── LoginStore.cpp │ ├── LoginStore.hpp │ ├── Otp.cpp │ ├── Otp.hpp │ ├── RecoveryQuestions.cpp │ ├── RecoveryQuestions.hpp │ ├── Sharing.cpp │ ├── Sharing.hpp │ ├── json │ │ ├── AuthJson.cpp │ │ ├── AuthJson.hpp │ │ ├── KeyJson.hpp │ │ ├── LoginJson.cpp │ │ ├── LoginJson.hpp │ │ └── LoginPackages.hpp │ └── server │ │ ├── AirbitzRequest.cpp │ │ ├── AirbitzRequest.hpp │ │ ├── LoginServer.cpp │ │ ├── LoginServer.hpp │ │ ├── Pinning.cpp │ │ └── Pinning.hpp ├── util │ ├── AutoFree.hpp │ ├── Data.cpp │ ├── Data.hpp │ ├── Debug.cpp │ ├── Debug.hpp │ ├── FileIO.cpp │ ├── FileIO.hpp │ ├── Status.cpp │ ├── Status.hpp │ ├── Sync.cpp │ ├── Sync.hpp │ ├── U08Buf.cpp │ ├── U08Buf.hpp │ ├── Util.cpp │ └── Util.hpp └── wallet │ ├── AddressDb.cpp │ ├── AddressDb.hpp │ ├── Metadata.cpp │ ├── Metadata.hpp │ ├── Receive.cpp │ ├── Receive.hpp │ ├── TxDb.cpp │ ├── TxDb.hpp │ ├── Wallet.cpp │ └── Wallet.hpp ├── astyle-options ├── cli ├── Command.cpp ├── Command.hpp ├── Main.cpp ├── abc-cli-bash-completion.sh ├── airbitz.conf ├── ca-certificates.crt ├── commands │ ├── Account.cpp │ ├── Address.cpp │ ├── Bitid.cpp │ ├── Categories.cpp │ ├── Commands.cpp │ ├── Exchange.cpp │ ├── Hiddenbits.cpp │ ├── Lobby.cpp │ ├── Otp.cpp │ ├── Pin.cpp │ ├── Plugin.cpp │ ├── Recovery.cpp │ ├── Recovery2.cpp │ ├── Repo.cpp │ ├── Settings.cpp │ ├── Spend.cpp │ ├── Stratum.cpp │ ├── Wallet.cpp │ └── Watcher.cpp └── doc │ ├── .gitignore │ ├── README.md │ └── abc-cli.pod ├── deps ├── .gitignore ├── Makefile ├── abc-cli ├── abc-watcher ├── classes │ ├── android │ ├── android.toolchain.cmake │ ├── common │ ├── ios │ ├── ios.toolchain.cmake │ ├── lib │ ├── native │ ├── native.cmake │ ├── osx │ └── osx.toolchain.cmake ├── documentation.md ├── make-testnet ├── mk-abc-only ├── recipes │ ├── abc │ │ └── abc.recipe │ ├── boost │ │ ├── boost.recipe │ │ ├── fix-asio-android.patch │ │ └── user-config.jam │ ├── curl │ │ └── curl.recipe │ ├── jansson │ │ └── jansson.recipe │ ├── libbitcoin │ │ ├── config.patch │ │ └── libbitcoin.recipe │ ├── libcsv │ │ └── libcsv.recipe │ ├── libgit2 │ │ ├── ios-build.patch │ │ ├── libgit2.recipe │ │ ├── pinning.patch │ │ └── timeout.patch │ ├── libqrencode │ │ └── libqrencode.recipe │ ├── libsecp256k1 │ │ ├── libsecp256k1.recipe │ │ └── optimize.patch │ ├── libsodium │ │ └── libsodium.recipe │ ├── ndk │ │ ├── langinfo.h │ │ └── ndk.recipe │ ├── openssl │ │ └── openssl.recipe │ ├── protobuf │ │ └── protobuf.recipe │ ├── zeromq │ │ ├── ios-crash.patch │ │ └── zeromq.recipe │ └── zlib │ │ └── zlib.recipe └── run.sh ├── minilibs ├── catch │ ├── catch.hpp │ └── readme.md ├── git-sync │ ├── .gitignore │ ├── Makefile │ ├── main.c │ ├── readme.md │ ├── sync.c │ ├── sync.h │ └── test.c ├── libbitcoin-client │ ├── client.hpp │ ├── message_stream.hpp │ ├── obelisk_codec.cpp │ ├── obelisk_codec.hpp │ ├── obelisk_router.cpp │ ├── obelisk_router.hpp │ ├── obelisk_types.hpp │ ├── sleeper.hpp │ ├── zeromq_socket.cpp │ └── zeromq_socket.hpp └── scrypt │ ├── .gitignore │ ├── Makefile │ ├── crypto_scrypt.c │ ├── crypto_scrypt.h │ ├── readme.md │ └── sysendian.h ├── readme.md ├── remove-build-tags.sh ├── src ├── .gitignore ├── ABC.cpp ├── ABC.h ├── HandleCache.hpp ├── LoginShim.cpp ├── LoginShim.hpp ├── TxDetails.cpp ├── TxDetails.hpp ├── TxInfo.cpp ├── TxInfo.hpp └── Version.h.in ├── style.md ├── test ├── Bitcoin.cpp ├── Bitid.cpp ├── Crypto.cpp ├── Encoding.cpp ├── Json.cpp ├── Main.cpp ├── OtpKey.cpp ├── Scrypt.cpp ├── TxCache.cpp └── Uri.cpp └── util ├── .gitignore ├── airbitz-keygen.sh ├── airbitz-pubkeygen.sh └── git-hooks └── pre-commit /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [Makefile] 11 | indent_size = 8 12 | indent_style = tab 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.vpj 3 | *.vpw 4 | *.vpwhistu 5 | *~ 6 | .*.swp 7 | .DS_Store 8 | /build 9 | /codegen 10 | *.idea* 11 | *CMakeLists* 12 | pod2htmd.tmp 13 | 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Authors: 2 | 3 | * Tim Horton 4 | tim 'at' airbitz.co 5 | 6 | * William Swanson 7 | william 'at' airbitz.co 8 | 9 | * Paul Puey 10 | paul 'at' airbitz.co 11 | 12 | * Adam Harris 13 | adam 'at' dittylabs.com 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Airbitz Inc 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms are permitted provided that 5 | the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 3. Redistribution or use of modified source code requires the express written 13 | permission of Airbitz Inc. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | The views and conclusions contained in the software and documentation are those 27 | of the authors and should not be interpreted as representing official policies, 28 | either expressed or implied, of the Airbitz Project. 29 | 30 | 31 | -------------------------------------------------------------------------------- /abc-cli: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | program=build/abc-cli 3 | make $program && ./$program "$@" 4 | -------------------------------------------------------------------------------- /abc-watcher: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | program=build/abc-watcher 3 | make $program && ./$program "$@" 4 | -------------------------------------------------------------------------------- /abcd/AccountPaths.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ACCOUNT_PATHS_HPP 9 | #define ABCD_ACCOUNT_PATHS_HPP 10 | 11 | #include "util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | /** 16 | * Knows how to calculate paths within a login directory. 17 | */ 18 | class AccountPaths 19 | { 20 | public: 21 | AccountPaths(): ok_(false) {} 22 | AccountPaths(const std::string &dir): ok_(true), dir_(dir) {} 23 | 24 | bool ok() const { return ok_; } 25 | 26 | // Directories: 27 | const std::string &dir() const { return dir_; } 28 | std::string syncDir() const { return dir_ + "sync/"; } 29 | std::string walletsDir() const { return dir_ + "sync/Wallets/"; } 30 | 31 | // Files: 32 | std::string carePackagePath() const { return dir_ + "CarePackage.json"; } 33 | std::string loginPackagePath() const { return dir_ + "LoginPackage.json"; } 34 | std::string pinPackagePath() const { return dir_ + "PinPackage.json"; } 35 | std::string otpKeyPath() const { return dir_ + "OtpKey.json"; } 36 | std::string pin2KeyPath() const { return dir_ + "Pin2Key.json"; } 37 | std::string recovery2KeyPath() const { return dir_ + "Recovery2Key.json"; } 38 | std::string rootKeyPath() const { return dir_ + "RootKey.json"; } 39 | std::string stashPath() const { return dir_ + "Stash.json"; } 40 | 41 | private: 42 | bool ok_; 43 | std::string dir_; 44 | }; 45 | 46 | } // namespace abcd 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /abcd/Context.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Context.hpp" 9 | #include "bitcoin/cache/BlockCache.hpp" 10 | #include "exchange/ExchangeCache.hpp" 11 | #include "bitcoin/cache/ServerCache.hpp" 12 | 13 | namespace abcd { 14 | 15 | std::unique_ptr gContext; 16 | 17 | Context::~Context() 18 | { 19 | delete &blockCache; 20 | delete &exchangeCache; 21 | } 22 | 23 | Context::Context(const std::string &rootDir, const std::string &certPath, 24 | const std::string &apiKey, 25 | const std::string &accountType, 26 | const std::string &hiddenBitsKey): 27 | apiKey_(apiKey), 28 | accountType_(accountType), 29 | hiddenBitsKey_(hiddenBitsKey), 30 | paths(rootDir, certPath), 31 | blockCache(*new BlockCache(paths.blockCachePath())), 32 | exchangeCache(*new ExchangeCache(paths.exchangeCachePath())), 33 | serverCache(*new ServerCache(paths.serverScoresPath())) 34 | { 35 | blockCache.load().log(); // Failure is fine 36 | } 37 | 38 | } // namespace abcd 39 | -------------------------------------------------------------------------------- /abcd/Context.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_CONTEXT_H 9 | #define ABCD_CONTEXT_H 10 | 11 | #include "RootPaths.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | class BlockCache; 17 | class ExchangeCache; 18 | class ServerCache; 19 | 20 | /** 21 | * An object holding app-wide information, such as paths. 22 | */ 23 | class Context 24 | { 25 | public: 26 | ~Context(); 27 | Context(const std::string &rootDir, const std::string &certPath, 28 | const std::string &apiKey, 29 | const std::string &accountType, 30 | const std::string &hiddenBitsKey); 31 | 32 | const std::string &apiKey() const { return apiKey_; } 33 | const std::string &accountType() const { return accountType_; } 34 | const std::string &hiddenBitsKey() const { return hiddenBitsKey_; } 35 | 36 | private: 37 | const std::string apiKey_; 38 | const std::string accountType_; 39 | const std::string hiddenBitsKey_; 40 | 41 | public: 42 | RootPaths paths; 43 | BlockCache &blockCache; 44 | ExchangeCache &exchangeCache; 45 | ServerCache &serverCache; 46 | }; 47 | 48 | /** 49 | * The global context instance. 50 | */ 51 | extern std::unique_ptr gContext; 52 | 53 | } // namespace abcd 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /abcd/Export.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Functions for exporting wallet meta-data. 10 | */ 11 | 12 | #ifndef ABC_Export_h 13 | #define ABC_Export_h 14 | 15 | #include "util/Status.hpp" 16 | 17 | namespace abcd { 18 | 19 | tABC_CC ABC_ExportFormatCsv(tABC_TxInfo **pTransactions, 20 | unsigned int iTransactionCount, 21 | char **szCsvData, 22 | tABC_Error *pError, 23 | std::string currency); 24 | 25 | Status 26 | exportFormatQBO(std::string &result, tABC_TxInfo **pTransactions, 27 | unsigned int iTransactionCount, std::string currency); 28 | 29 | } // namespace abcd 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /abcd/RootPaths.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ROOT_PATHS_HPP 9 | #define ABCD_ROOT_PATHS_HPP 10 | 11 | #include "util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | class AccountPaths; 17 | class WalletPaths; 18 | 19 | /** 20 | * Knows how to calculate paths at the top-level of the app. 21 | */ 22 | class RootPaths 23 | { 24 | public: 25 | RootPaths(const std::string &rootDir, const std::string &certPath); 26 | 27 | // Directories: 28 | const std::string &rootDir() const { return dir_; } 29 | std::string accountsDir() const; 30 | std::string walletsDir() const { return dir_ + "Wallets/"; } 31 | 32 | /** 33 | * Lists the accounts on the device. 34 | */ 35 | std::list 36 | accountList(); 37 | 38 | /** 39 | * Finds the account directory for a particular username. 40 | * Returns an empty string if the account does not exist on the device. 41 | */ 42 | Status 43 | accountDir(AccountPaths &result, const std::string &username); 44 | 45 | /** 46 | * Creates a fresh directory for a new account. 47 | */ 48 | Status 49 | accountDirNew(AccountPaths &result, const std::string &username); 50 | 51 | /** 52 | * Returns the directory name for a particular wallet. 53 | */ 54 | WalletPaths 55 | walletDir(const std::string &id); 56 | 57 | // Individual files: 58 | const std::string &certPath() const { return certPath_; } 59 | std::string blockCachePath() const { return dir_ + "Blocks.json"; } 60 | std::string exchangeCachePath() const { return dir_ + "Exchange.json"; } 61 | std::string feeCachePath() const { return dir_ + "Fees.json"; } 62 | std::string twentyOneFeeCachePath() const { return dir_ + "TwentyOneFees.json"; } 63 | std::string generalPath() const { return dir_ + "Servers.json"; } 64 | std::string serverScoresPath() const { return dir_ + "ServerScores.json"; } 65 | std::string questionsPath() const { return dir_ + "Questions.json"; } 66 | std::string logPath() const { return dir_ + "abc.log"; } 67 | std::string logPrevPath() const { return dir_ + "abc-prev.log"; } 68 | 69 | private: 70 | const std::string dir_; 71 | const std::string certPath_; 72 | }; 73 | 74 | } // namespace abcd 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /abcd/WalletPaths.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, AirBitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_WALLET_PATHS_HPP 9 | #define ABCD_WALLET_PATHS_HPP 10 | 11 | #include "util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * Knows how to calculate paths within a wallet directory. 18 | */ 19 | class WalletPaths 20 | { 21 | public: 22 | WalletPaths(const std::string &walletDir): dir_(walletDir) {} 23 | 24 | // Directories: 25 | const std::string &dir() const { return dir_; } 26 | std::string syncDir() const { return dir_ + "sync/"; } 27 | std::string addressesDir() const { return dir_ + "sync/Addresses/"; } 28 | std::string txsDir() const { return dir_ + "sync/Transactions/"; } 29 | 30 | // Files: 31 | std::string currencyPath() const { return dir_ + "sync/Currency.json"; } 32 | std::string namePath() const { return dir_ + "sync/WalletName.json"; } 33 | std::string cachePath() const { return dir_ + "Cache.json"; } 34 | std::string cachePathOld() const { return dir_ + "watcher.ser"; } 35 | 36 | private: 37 | std::string dir_; 38 | }; 39 | 40 | } // namespace abcd 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /abcd/account/Account.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Account.hpp" 9 | #include "../Context.hpp" 10 | #include "../crypto/Encoding.hpp" 11 | #include "../login/Login.hpp" 12 | #include "../login/json/KeyJson.hpp" 13 | #include "../util/Sync.hpp" 14 | 15 | namespace abcd { 16 | 17 | Status 18 | Account::create(std::shared_ptr &result, Login &login) 19 | { 20 | AccountRepoJson repoJson; 21 | ABC_CHECK(login.repoFind(repoJson, gContext->accountType(), true)); 22 | DataChunk dataKey; 23 | DataChunk syncKey; 24 | ABC_CHECK(base64Decode(dataKey, repoJson.dataKey())); 25 | ABC_CHECK(base64Decode(syncKey, repoJson.syncKey())); 26 | std::shared_ptr out(new Account(login, dataKey, syncKey)); 27 | ABC_CHECK(out->load()); 28 | 29 | result = std::move(out); 30 | return Status(); 31 | } 32 | 33 | Status 34 | Account::sync(bool &dirty) 35 | { 36 | ABC_CHECK(syncRepo(dir(), syncKey_, dirty)); 37 | if (dirty) 38 | ABC_CHECK(load()); 39 | 40 | return Status(); 41 | } 42 | 43 | Account::Account(Login &login, DataSlice dataKey, DataSlice syncKey): 44 | login(login), 45 | parent_(login.shared_from_this()), 46 | dir_(login.paths.syncDir()), 47 | dataKey_(dataKey.begin(), dataKey.end()), 48 | syncKey_(base16Encode(syncKey)), 49 | wallets(*this) 50 | {} 51 | 52 | Status 53 | Account::load() 54 | { 55 | // If the sync dir doesn't exist, create it: 56 | const auto tempPath = login.paths.dir() + "tmp/"; 57 | ABC_CHECK(syncEnsureRepo(dir(), tempPath, syncKey_)); 58 | 59 | ABC_CHECK(wallets.load()); 60 | return Status(); 61 | } 62 | 63 | } // namespace abcd 64 | -------------------------------------------------------------------------------- /abcd/account/Account.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ACCOUNT_ACCOUNT_HPP 9 | #define ABCD_ACCOUNT_ACCOUNT_HPP 10 | 11 | #include "WalletList.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | class Login; 17 | 18 | /** 19 | * Manages the account sync directory. 20 | */ 21 | class Account: 22 | public std::enable_shared_from_this 23 | { 24 | public: 25 | Login &login; 26 | 27 | static Status 28 | create(std::shared_ptr &result, Login &login); 29 | 30 | const std::string &dir() const { return dir_; } 31 | const DataChunk &dataKey() const { return dataKey_; } 32 | 33 | /** 34 | * Syncs the account with the file server. 35 | * This is a blocking network operation. 36 | */ 37 | Status 38 | sync(bool &dirty); 39 | 40 | private: 41 | const std::shared_ptr parent_; 42 | const std::string dir_; 43 | const DataChunk dataKey_; 44 | const std::string syncKey_; 45 | 46 | Account(Login &login, DataSlice dataKey, DataSlice syncKey); 47 | 48 | Status 49 | load(); 50 | 51 | public: 52 | WalletList wallets; 53 | 54 | // Set to the current PIN when the settings are loaded. 55 | // Used to detect changes to the PIN. 56 | std::string pin; 57 | }; 58 | 59 | } // namespace abcd 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /abcd/account/AccountCategories.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "AccountCategories.hpp" 9 | #include "Account.hpp" 10 | #include "../json/JsonArray.hpp" 11 | #include "../json/JsonObject.hpp" 12 | #include "../login/Login.hpp" 13 | 14 | namespace abcd { 15 | 16 | struct CategoriesJson: 17 | public JsonObject 18 | { 19 | ABC_JSON_VALUE(categories, "categories", JsonArray); 20 | }; 21 | 22 | static std::string 23 | categoriesPath(const Account &account) 24 | { 25 | return account.dir() + "Categories.json"; 26 | } 27 | 28 | Status 29 | accountCategoriesSave(const Account &account, 30 | const AccountCategories &categories) 31 | { 32 | JsonArray arrayJson; 33 | for (auto &i: categories) 34 | { 35 | ABC_CHECK(arrayJson.append(json_string(i.c_str()))); 36 | } 37 | 38 | CategoriesJson json; 39 | ABC_CHECK(json.categoriesSet(arrayJson)); 40 | ABC_CHECK(json.save(categoriesPath(account), account.dataKey())); 41 | 42 | return Status(); 43 | } 44 | 45 | Status 46 | accountCategoriesLoad(AccountCategories &result, const Account &account) 47 | { 48 | AccountCategories out; 49 | 50 | CategoriesJson json; 51 | ABC_CHECK(json.load(categoriesPath(account), account.dataKey())); 52 | 53 | auto arrayJson = json.categories(); 54 | size_t size = arrayJson.size(); 55 | for (size_t i = 0; i < size; i++) 56 | { 57 | auto stringJson = arrayJson[i]; 58 | if (!json_is_string(stringJson.get())) 59 | return ABC_ERROR(ABC_CC_JSONError, "Category is not a string"); 60 | 61 | out.insert(json_string_value(stringJson.get())); 62 | } 63 | 64 | result = std::move(out); 65 | return Status(); 66 | } 67 | 68 | Status 69 | accountCategoriesAdd(const Account &account, const std::string &category) 70 | { 71 | AccountCategories categories; 72 | accountCategoriesLoad(categories, account); 73 | categories.insert(category); 74 | ABC_CHECK(accountCategoriesSave(account, categories)); 75 | return Status(); 76 | } 77 | 78 | Status 79 | accountCategoriesRemove(const Account &account, const std::string &category) 80 | { 81 | AccountCategories categories; 82 | ABC_CHECK(accountCategoriesLoad(categories, account)); 83 | categories.erase(category); 84 | ABC_CHECK(accountCategoriesSave(account, categories)); 85 | return Status(); 86 | } 87 | 88 | } // namespace abcd 89 | -------------------------------------------------------------------------------- /abcd/account/AccountCategories.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ACCOUNT_ACCOUNT_CATEGORIES_HPP 9 | #define ABCD_ACCOUNT_ACCOUNT_CATEGORIES_HPP 10 | 11 | #include "../util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | class Account; 17 | 18 | typedef std::set AccountCategories; 19 | 20 | /** 21 | * Loads the categories from an account. 22 | */ 23 | Status 24 | accountCategoriesLoad(AccountCategories &result, const Account &account); 25 | 26 | /** 27 | * Adds a category to the account. 28 | */ 29 | Status 30 | accountCategoriesAdd(const Account &account, const std::string &category); 31 | 32 | /** 33 | * Removes a category from the account. 34 | */ 35 | Status 36 | accountCategoriesRemove(const Account &account, const std::string &category); 37 | 38 | } // namespace abcd 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /abcd/account/AccountSettings.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ACCOUNT_ACCOUNT_SETTINGS_HPP 9 | #define ABCD_ACCOUNT_ACCOUNT_SETTINGS_HPP 10 | 11 | #include "../util/Status.hpp" 12 | 13 | #define DEFAULT_SERVER_LIST "stratum://electrum.airbitz.co\nstratum://electrum-bu-az-weuro.airbitz.co:50001\nstratum://electrum-bu-az-wjapan.airbitz.co:50001\nstratum://electrum-bc-az-eusa.airbitz.co:50001" 14 | 15 | // Miminum possible server string. ie. "stratum://e.c:1" 16 | #define SERVER_STRING_LEN_MINIMUM 15 17 | 18 | namespace abcd { 19 | 20 | class Account; 21 | class Login; 22 | 23 | /** 24 | * Loads the settings from an account. 25 | * Returns default settings if anything goes wrong. 26 | */ 27 | tABC_AccountSettings * 28 | accountSettingsLoad(Account &account); 29 | 30 | /** 31 | * Saves the settings for an account. 32 | */ 33 | Status 34 | accountSettingsSave(Account &account, tABC_AccountSettings *pSettings); 35 | 36 | /** 37 | * Frees the account settings structure, along with its contents. 38 | */ 39 | void 40 | accountSettingsFree(tABC_AccountSettings *pSettings); 41 | 42 | } // namespace abcd 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /abcd/account/PluginData.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ACCOUNT_PLUGIN_DATA_HPP 9 | #define ABCD_ACCOUNT_PLUGIN_DATA_HPP 10 | 11 | #include "../util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | class Account; 17 | 18 | /** 19 | * Lists the plugin key/value stores in the account. 20 | * This mainly exists for diagnostics, 21 | * since the idea is that all plugins are sandboxed by their plugin id. 22 | * There shouldn't be any code that needs to list the plugin id's, 23 | * since the list should be static and know ahead of time. 24 | */ 25 | std::list 26 | pluginDataList(const Account &account); 27 | 28 | /** 29 | * Lists the keys in a plugin key/value store. 30 | */ 31 | std::list 32 | pluginDataKeys(const Account &account, const std::string &plugin); 33 | 34 | /** 35 | * Retreives an item from the plugin key/value store. 36 | * @param plugin The plugin's unique ID. 37 | * @param key The data location. Merges happen at the key level, 38 | * so the account may contain a mix of keys from different devices. 39 | * The key contents are atomic, however. Place data accordingly. 40 | * @param data The value stored with the key. 41 | */ 42 | Status 43 | pluginDataGet(const Account &account, const std::string &plugin, 44 | const std::string &key, std::string &data); 45 | 46 | /** 47 | * Saves an item to the plugin key/value store. 48 | */ 49 | Status 50 | pluginDataSet(const Account &account, const std::string &plugin, 51 | const std::string &key, const std::string &data); 52 | 53 | /** 54 | * Deletes an item from the plugin key/value store. 55 | */ 56 | Status 57 | pluginDataRemove(const Account &account, const std::string &plugin, 58 | const std::string &key); 59 | 60 | /** 61 | * Removes the entire key/value store for a particular plugin. 62 | */ 63 | Status 64 | pluginDataClear(const Account &account, const std::string &plugin); 65 | 66 | } // namespace abcd 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /abcd/account/WalletList.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_ACCOUNT_WALLET_LIST_HPP 9 | #define ABCD_ACCOUNT_WALLET_LIST_HPP 10 | 11 | #include "../json/JsonPtr.hpp" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace abcd { 17 | 18 | class Account; 19 | 20 | /** 21 | * Manages the list of wallets stored under the account sync directory. 22 | * Uses a write-through caching scheme, where changes go straight to disk, 23 | * but queries come out of RAM. 24 | */ 25 | class WalletList 26 | { 27 | public: 28 | WalletList(const Account &account); 29 | 30 | /** 31 | * Loads the wallets off disk. 32 | * This should be done after logging in and after a dirty sync. 33 | */ 34 | Status 35 | load(); 36 | 37 | /** 38 | * Obtains a sorted list of wallets. 39 | */ 40 | std::list 41 | list() const; 42 | 43 | /** 44 | * Adjusts the sort index of a wallet. 45 | */ 46 | Status 47 | reorder(const std::string &id, unsigned index); 48 | 49 | /** 50 | * Adds a new wallet to the account. 51 | */ 52 | Status 53 | insert(const std::string &id, const JsonPtr &keys); 54 | 55 | /** 56 | * Remove a wallet. 57 | */ 58 | Status 59 | remove(const std::string &id); 60 | 61 | /** 62 | * Returns the meta-data file for a wallet. 63 | * The wallet stores its keys and seeds in here. 64 | */ 65 | Status 66 | json(JsonPtr &result, const std::string &id) const; 67 | 68 | /** 69 | * Returns the archived state for the given id. 70 | */ 71 | Status 72 | archived(bool &result, const std::string &id) const; 73 | 74 | /** 75 | * Adjusts the archived status of a wallet. 76 | */ 77 | Status 78 | archivedSet(const std::string &id, bool archived); 79 | 80 | private: 81 | mutable std::mutex mutex_; 82 | const Account &account_; 83 | const std::string dir_; 84 | 85 | std::map wallets_; 86 | 87 | /** 88 | * Builds the path to a wallet file. 89 | */ 90 | std::string 91 | path(const std::string &name) const; 92 | }; 93 | 94 | } // namespace abcd 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /abcd/bitcoin/Testnet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Testnet.hpp" 9 | #include 10 | 11 | namespace abcd { 12 | 13 | bool isTestnet() 14 | { 15 | bc::payment_address foo; 16 | bc::set_public_key_hash(foo, bc::null_short_hash); 17 | return foo.version() != 0x00; 18 | } 19 | 20 | uint8_t pubkeyVersion() 21 | { 22 | if (isTestnet()) 23 | return 0x6f; 24 | return 0x00; 25 | } 26 | 27 | uint8_t scriptVersion() 28 | { 29 | if (isTestnet()) 30 | return 0xc4; 31 | return 0x05; 32 | } 33 | 34 | } // namespace abcd 35 | -------------------------------------------------------------------------------- /abcd/bitcoin/Testnet.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Routines for dealing with testnet/mainnet differences. 10 | */ 11 | 12 | #ifndef ABCD_BITCOIN_TESTNET_HPP 13 | #define ABCD_BITCOIN_TESTNET_HPP 14 | 15 | #include 16 | 17 | namespace abcd { 18 | 19 | /** 20 | * Returns true if libbitcoin has been compiled with testnet support. 21 | */ 22 | bool isTestnet(); 23 | 24 | /** 25 | * Returns the version byte for a pubkey address. 26 | * Depends on whether or not testnet is turned on. 27 | */ 28 | uint8_t pubkeyVersion(); 29 | 30 | /** 31 | * Returns the version byte for a p2sh address. 32 | * Depends on whether or not testnet is turned on. 33 | */ 34 | uint8_t scriptVersion(); 35 | 36 | } // namespace abcd 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /abcd/bitcoin/Text.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Helpers for dealing with Bitcoin-related text formats. 10 | */ 11 | 12 | #ifndef ABCD_BITCOIN_TEXT_HPP 13 | #define ABCD_BITCOIN_TEXT_HPP 14 | 15 | #include "../util/Status.hpp" 16 | 17 | namespace abcd { 18 | 19 | /** 20 | * All the fields that can be found in a URI, bitcoin address, or private key. 21 | */ 22 | struct ParsedUri 23 | { 24 | // Top-level actions: 25 | std::string address; 26 | std::string wif; 27 | std::string paymentProto; 28 | std::string bitidUri; 29 | 30 | // URI parameters: 31 | uint64_t amountSatoshi = 0; 32 | std::string label; 33 | std::string message; 34 | std::string category; // Airbitz extension 35 | std::string ret; // Airbitz extension 36 | 37 | // BitID metadata requests: 38 | bool bitidPaymentAddress = false; 39 | bool bitidKycProvider = false; 40 | bool bitidKycRequest = false; 41 | }; 42 | 43 | /** 44 | * Decodes a URI, bitcoin address, or private key. 45 | */ 46 | Status 47 | parseUri(ParsedUri &result, const std::string &text); 48 | 49 | /** 50 | * Generate a random hbits private key. 51 | */ 52 | Status 53 | hbitsCreate(std::string &result, std::string &addressOut); 54 | 55 | /** 56 | * Trims the spaces off the ends of a string. 57 | */ 58 | std::string 59 | trimSpace(std::string text); 60 | 61 | } // namespace abcd 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /abcd/bitcoin/Typedefs.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * General bitcoin data types. 10 | */ 11 | 12 | #ifndef ABCD_BITCOIN_TYPES_HPP 13 | #define ABCD_BITCOIN_TYPES_HPP 14 | 15 | #include "../util/Status.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | namespace libbitcoin { 21 | 22 | struct block_header_type; 23 | struct transaction_type; 24 | 25 | } // namespace libbitcoin 26 | 27 | namespace abcd { 28 | 29 | typedef std::set AddressSet; 30 | typedef std::set TxidSet; 31 | 32 | typedef std::function StatusCallback; 33 | 34 | } // namespace abcd 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /abcd/bitcoin/Utility.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Utility functions that should probably go into libbitcoin one day. 10 | */ 11 | 12 | #ifndef ABCD_BITCOIN_UTILITY_HPP 13 | #define ABCD_BITCOIN_UTILITY_HPP 14 | 15 | #include "../util/Status.hpp" 16 | #include 17 | 18 | namespace abcd { 19 | 20 | /** 21 | * Calculates the non-malleable id for a transaction. 22 | */ 23 | bc::hash_digest 24 | makeNtxid(bc::transaction_type tx); 25 | 26 | /** 27 | * Returns true if a transaction opts in to RBF semantics. 28 | */ 29 | bool 30 | isReplaceByFee(const bc::transaction_type &tx); 31 | 32 | /** 33 | * Bundles the provided data into a script push operation. 34 | */ 35 | bc::operation 36 | makePushOperation(bc::data_slice data); 37 | 38 | /** 39 | * Decodes a blob of raw data into a transaction. 40 | */ 41 | Status 42 | decodeTx(bc::transaction_type &result, bc::data_slice rawTx); 43 | 44 | /** 45 | * Decodes a blob of raw data into a block header. 46 | */ 47 | Status 48 | decodeHeader(bc::block_header_type &result, bc::data_slice rawHeader); 49 | 50 | } // namespace abcd 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /abcd/bitcoin/Watcher.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_BITCOIN_WATCHER_HPP 9 | #define ABCD_BITCOIN_WATCHER_HPP 10 | 11 | #include "network/TxUpdater.hpp" 12 | #include "../wallet/Wallet.hpp" 13 | #include 14 | #include 15 | 16 | namespace abcd { 17 | 18 | /** 19 | * Provides threading support for the TxUpdater object. 20 | */ 21 | class Watcher 22 | { 23 | public: 24 | Watcher(Wallet &wallet); 25 | 26 | // - Updater messages: ------------- 27 | void sendWakeup(); 28 | void disconnect(); 29 | void connect(); 30 | void sendTx(StatusCallback status, DataSlice tx); 31 | 32 | // - Thread implementation: -------- 33 | 34 | /** 35 | * Tells the loop() method to return. 36 | */ 37 | void stop(); 38 | 39 | /** 40 | * Call this function from a separate thread. It will run for an 41 | * unlimited amount of time as it works to keep the transactions 42 | * in the watcher up-to-date with the network. The function will 43 | * eventually return when the watcher object is destroyed. 44 | */ 45 | void loop(); 46 | 47 | Watcher(const Watcher ©) = delete; 48 | Watcher &operator=(const Watcher ©) = delete; 49 | 50 | private: 51 | // Socket for talking to the thread: 52 | std::mutex socket_mutex_; 53 | std::string socket_name_; 54 | zmq::socket_t socket_; 55 | 56 | // Everything below this point is only touched by the thread: 57 | bool command(uint8_t *data, size_t size); 58 | 59 | // This needs to be constructed last, since it uses everything else: 60 | TxUpdater txu_; 61 | }; 62 | 63 | } // namespace abcd 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /abcd/bitcoin/WatcherBridge.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Caching and utility wrapper layer around the bitcoin `watcher` class. 10 | * 11 | * There was a time when `watcher` was part of libbitcoin-watcher, 12 | * and the AirBitz software was plain C. 13 | * This module used to bridge the gap between those two worlds, 14 | * but now it is less useful. 15 | */ 16 | 17 | #ifndef ABC_Bridge_h 18 | #define ABC_Bridge_h 19 | 20 | #include "Typedefs.hpp" 21 | #include "../util/Data.hpp" 22 | 23 | namespace abcd { 24 | 25 | class Wallet; 26 | 27 | Status 28 | bridgeSweepKey(Wallet &self, const std::string &wif, 29 | const std::string &address); 30 | 31 | Status 32 | bridgeWatcherStart(Wallet &self); 33 | 34 | Status 35 | bridgeWatcherLoop(Wallet &self, 36 | tABC_BitCoin_Event_Callback fCallback, 37 | void *pData); 38 | 39 | Status 40 | bridgeWatcherConnect(Wallet &self); 41 | 42 | Status 43 | bridgeWatcherDisconnect(Wallet &self); 44 | 45 | Status 46 | bridgeWatcherStop(Wallet &self); 47 | 48 | Status 49 | bridgeWatcherDelete(Wallet &self); 50 | 51 | Status 52 | watcherSend(Wallet &self, StatusCallback status, DataSlice rawTx); 53 | 54 | } // namespace abcd 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /abcd/bitcoin/cache/Cache.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_BITCOIN_CACHE_CACHE_HPP 9 | #define ABCD_BITCOIN_CACHE_CACHE_HPP 10 | 11 | #include "AddressCache.hpp" 12 | #include "BlockCache.hpp" 13 | #include "TxCache.hpp" 14 | #include "ServerCache.hpp" 15 | 16 | namespace abcd { 17 | 18 | class Cache 19 | { 20 | public: 21 | TxCache txs; 22 | BlockCache &blocks; 23 | AddressCache addresses; 24 | ServerCache &servers; 25 | 26 | Cache(const std::string &path, BlockCache &blockCache, 27 | ServerCache &serverCache); 28 | 29 | /** 30 | * Sets the address check done for this wallet meaning that 31 | * this wallet has had all addresses checked at least once on 32 | * this device 33 | */ 34 | void 35 | addressCheckDoneSet(); 36 | 37 | /** 38 | * Gets the address check done for this wallet meaning that 39 | * this wallet has had all addresses checked at least once on 40 | * this device 41 | */ 42 | bool 43 | addressCheckDoneGet(); 44 | 45 | /** 46 | * Clears the cache in case something goes wrong. 47 | */ 48 | void 49 | clear(); 50 | 51 | /** 52 | * Loads the cache from disk. 53 | */ 54 | Status 55 | load(); 56 | 57 | /** 58 | * Loads the cache from the legacy format. 59 | */ 60 | Status 61 | loadLegacy(const std::string &path); 62 | 63 | /** 64 | * Saves the cache to disk. 65 | */ 66 | Status 67 | save(); 68 | 69 | private: 70 | 71 | /** 72 | * Save the status of addressCheckDone in the cache 73 | */ 74 | Status 75 | addressCheckDoneSave(JsonObject &json); 76 | 77 | /** 78 | * Load the status of addressCheckDone from the cache 79 | */ 80 | void 81 | addressCheckDoneLoad(JsonObject &json); 82 | 83 | const std::string path_; 84 | bool addressCheckDone_; 85 | }; 86 | 87 | } // namespace abcd 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /abcd/bitcoin/cache/ServerCache.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_BITCOIN_SERVER_CACHE_HPP 9 | #define ABCD_BITCOIN_SERVER_CACHE_HPP 10 | 11 | #include "../../util/Status.hpp" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace abcd { 20 | 21 | typedef enum 22 | { 23 | ServerTypeStratum, 24 | ServerTypeAirbitz 25 | } ServerType; 26 | 27 | typedef struct 28 | { 29 | std::string serverUrl; 30 | int score; 31 | unsigned long responseTime; 32 | unsigned long numResponseTimes; 33 | } ServerInfo; 34 | 35 | /** 36 | * A block-height cache. 37 | */ 38 | class ServerCache 39 | { 40 | public: 41 | 42 | // Lifetime ------------------------------------------------------------ 43 | 44 | ServerCache(const std::string &path); 45 | 46 | /** 47 | * Clears the cache in case something goes wrong. 48 | */ 49 | void 50 | clear(); 51 | 52 | /** 53 | * Reads the database contents from disk. 54 | */ 55 | Status 56 | serverCacheLoad(); 57 | 58 | /** 59 | * Saves the database contents to disk, but only if there are changes. 60 | */ 61 | Status 62 | serverCacheSave(); 63 | 64 | /** 65 | * Increase server score 66 | */ 67 | Status 68 | serverScoreUp(std::string serverUrl, int changeScore=1); 69 | 70 | /** 71 | * Decrease server score 72 | */ 73 | Status 74 | serverScoreDown(std::string serverUrl, int changeScore=10); 75 | 76 | /** 77 | * Set the response time seen from an interaction with this server 78 | */ 79 | void 80 | setResponseTime(std::string serverUrl, 81 | unsigned long long responseTimeMilliseconds); 82 | 83 | /** 84 | * Get a vector of server URLs by type. This returns the top 'numServers' of servers with 85 | * the highest connectivity score 86 | */ 87 | std::vector 88 | getServers(ServerType type, unsigned int numServers); 89 | 90 | static 91 | unsigned long long getCurrentTimeMilliSeconds(); 92 | 93 | private: 94 | Status 95 | save_nolock(); 96 | 97 | mutable std::mutex mutex_; 98 | const std::string path_; 99 | bool dirty_; 100 | time_t lastUpScoreTime_; 101 | time_t cacheLastSave_; 102 | 103 | std::map servers_; 104 | }; 105 | 106 | } // namespace abcd 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /abcd/bitcoin/network/TcpConnection.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_BITCOIN_NETWORK_TCP_CONNECTION_HPP 9 | #define ABCD_BITCOIN_NETWORK_TCP_CONNECTION_HPP 10 | 11 | #include "../../util/Status.hpp" 12 | #include "../../util/Data.hpp" 13 | 14 | namespace abcd { 15 | 16 | class TcpConnection 17 | { 18 | public: 19 | ~TcpConnection(); 20 | TcpConnection(); 21 | 22 | /** 23 | * Connect to the specified server. 24 | */ 25 | Status 26 | connect(const std::string &hostname, unsigned port); 27 | 28 | /** 29 | * Send some data over the socket. 30 | */ 31 | Status 32 | send(DataSlice data); 33 | 34 | /** 35 | * Read all pending data from the socket (might not produce anything). 36 | */ 37 | Status 38 | read(DataChunk &result); 39 | 40 | /** 41 | * Obtains a list of sockets that the main loop should sleep on. 42 | */ 43 | int pollfd() const { return fd_; } 44 | 45 | private: 46 | int fd_; 47 | }; 48 | 49 | } // namespace abcd 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/AirbitzFee.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "AirbitzFee.hpp" 9 | #include "Spend.hpp" 10 | #include "../../General.hpp" 11 | #include "../../wallet/Wallet.hpp" 12 | 13 | namespace abcd { 14 | 15 | int64_t 16 | airbitzFeeOutgoing(const AirbitzFeeInfo &info, int64_t spent) 17 | { 18 | if (spent <= 0) 19 | return 0; 20 | int64_t fee = info.outgoingRate * spent; 21 | if (fee < info.noFeeMinSatoshi) 22 | return 0; 23 | if (fee < info.outgoingMin) 24 | fee = info.outgoingMin; 25 | if (info.outgoingMax < fee) 26 | fee = info.outgoingMax; 27 | return fee; 28 | } 29 | 30 | int64_t 31 | airbitzFeeIncoming(const AirbitzFeeInfo &info, int64_t received) 32 | { 33 | if (received <= 0) 34 | return 0; 35 | int64_t fee = info.incomingRate * received; 36 | if (fee < info.incomingMin) 37 | fee = info.incomingMin; 38 | if (info.incomingMax < fee) 39 | fee = info.incomingMax; 40 | return fee; 41 | } 42 | 43 | Status 44 | airbitzFeeAutoSend(Wallet &wallet) 45 | { 46 | const auto info = generalAirbitzFeeInfo(); 47 | if (info.addresses.empty()) 48 | return Status(); 49 | 50 | const auto owed = wallet.txs.airbitzFeePending(); 51 | if (owed < info.sendMin) 52 | return Status(); 53 | 54 | const auto last = wallet.txs.airbitzFeeLastSent(); 55 | if (time(nullptr) < last + info.sendPeriod) 56 | return Status(); 57 | 58 | Metadata metadata; 59 | metadata.name = info.sendPayee; 60 | metadata.category = info.sendCategory; 61 | 62 | Spend spend(wallet); 63 | ABC_CHECK(spend.metadataSet(metadata)); 64 | DataChunk rawTx; 65 | ABC_CHECK(spend.signTx(rawTx)); 66 | ABC_CHECK(spend.broadcastTx(rawTx)); 67 | std::string txid; 68 | ABC_CHECK(spend.saveTx(rawTx, txid)); 69 | 70 | return Status(); 71 | } 72 | 73 | } // namespace abcd 74 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/AirbitzFee.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_SPEND_AIRBITZ_FEE_HPP 9 | #define ABCD_SPEND_AIRBITZ_FEE_HPP 10 | 11 | #include "../../util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | struct AirbitzFeeInfo; 16 | class Wallet; 17 | 18 | /** 19 | * Calculates the fee owed for a spend. 20 | */ 21 | int64_t 22 | airbitzFeeOutgoing(const AirbitzFeeInfo &info, int64_t spent); 23 | 24 | /** 25 | * Calculates the fee owed for a receive. 26 | */ 27 | int64_t 28 | airbitzFeeIncoming(const AirbitzFeeInfo &info, int64_t received); 29 | 30 | /** 31 | * Sends an Airbitz fee if one is owed, and enough time has passed. 32 | */ 33 | Status 34 | airbitzFeeAutoSend(Wallet &wallet); 35 | 36 | } // namespace abcd 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/Broadcast.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_BITCOIN_BROADCAST_HPP 9 | #define ABCD_BITCOIN_BROADCAST_HPP 10 | 11 | #include "../../util/Data.hpp" 12 | #include "../../util/Status.hpp" 13 | 14 | namespace abcd { 15 | 16 | class Wallet; 17 | 18 | /** 19 | * Sends a transaction out to the Bitcoin network. 20 | */ 21 | Status 22 | broadcastTx(Wallet &self, DataSlice rawTx); 23 | 24 | } // namespace abcd 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/Inputs.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_BITCOIN_INPUTS_HPP 9 | #define ABCD_BITCOIN_INPUTS_HPP 10 | 11 | #include "../../util/Status.hpp" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace abcd { 17 | 18 | class TxCache; 19 | 20 | /** 21 | * Maps from Bitcoin addresses to WIF-encoded private keys. 22 | */ 23 | typedef std::map KeyTable; 24 | 25 | /** 26 | * Fills the transaction's inputs with signatures. 27 | */ 28 | Status 29 | signTx(bc::transaction_type &result, const TxCache &txCache, 30 | const KeyTable &keys); 31 | 32 | /** 33 | * Select a utxo collection that will satisfy the outputs as best possible 34 | * and calculate the resulting fees. 35 | */ 36 | Status 37 | inputsPickOptimal(uint64_t &resultFee, uint64_t &resultChange, 38 | bc::transaction_type &tx, const bc::output_info_list &utxos, 39 | tABC_SpendFeeLevel feeLevel, uint64_t customFeeSatoshi); 40 | 41 | /** 42 | * Populate the transaction's input list with all the utxo's in the wallet, 43 | * and calculate the mining fee using the already-present outputs. 44 | */ 45 | Status 46 | inputsPickMaximum(uint64_t &resultFee, uint64_t &resultUsable, 47 | bc::transaction_type &tx, const bc::output_info_list &utxos); 48 | 49 | } // namespace abcd 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/Outputs.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_SPEND_OUTPUTS_HPP 9 | #define ABCD_SPEND_OUTPUTS_HPP 10 | 11 | #include "../../util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * Creates an output script for sending money to an address. 18 | */ 19 | Status 20 | outputScriptForAddress(bc::script_type &result, const std::string &address); 21 | 22 | /** 23 | * Returns true if an amount is small enough to be considered dust. 24 | */ 25 | bool 26 | outputIsDust(uint64_t amount); 27 | 28 | /** 29 | * Add a change output, sort the outputs, and check for dust. 30 | */ 31 | Status 32 | outputsFinalize(bc::transaction_output_list &outputs, 33 | uint64_t change, const std::string &changeAddress); 34 | 35 | uint64_t 36 | outputsTotal(const bc::transaction_output_list &outputs); 37 | 38 | } // namespace abcd 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/PaymentProto.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_SPEND_PAYMENT_PROTO_HPP 9 | #define ABCD_SPEND_PAYMENT_PROTO_HPP 10 | 11 | #include "../../util/Data.hpp" 12 | #include "../../util/Status.hpp" 13 | #include "../../../codegen/paymentrequest.pb.h" 14 | 15 | #include 16 | 17 | namespace abcd { 18 | 19 | struct PaymentOutput 20 | { 21 | uint64_t amount; 22 | DataSlice script; 23 | }; 24 | 25 | struct PaymentReceipt 26 | { 27 | payments::PaymentACK ack; 28 | }; 29 | 30 | /** 31 | * Represents a request from the bip70 payment protocol. 32 | */ 33 | class PaymentRequest 34 | { 35 | public: 36 | /** 37 | * Fetches the initial payment request from the server. 38 | */ 39 | Status 40 | fetch(const std::string &url); 41 | 42 | /** 43 | * Returns true if the payment request is signed. 44 | */ 45 | bool 46 | signatureExists(); 47 | 48 | /** 49 | * Returns true if the certificate chain checks out. 50 | * Sets the result to the certificate domain name, 51 | * or URI authority if there is no certificate chain. 52 | */ 53 | Status 54 | signatureOk(std::string &result, const std::string &uri); 55 | 56 | /** 57 | * Obtains the payment scripts and amounts being requested. 58 | */ 59 | std::list 60 | outputs() const; 61 | 62 | /** 63 | * Obtain the total of all outputs. 64 | */ 65 | uint64_t 66 | amount() const; 67 | 68 | /** 69 | * Guesses the merchant name using a regex. 70 | */ 71 | std::string 72 | merchant(const std::string &fallback="") const; 73 | 74 | /** 75 | * Returns true if the request has a memo field. 76 | */ 77 | bool 78 | memoOk() const; 79 | 80 | /** 81 | * Returns the memo, if any. 82 | */ 83 | std::string 84 | memo(const std::string &fallback="") const; 85 | 86 | /** 87 | * Pays the payment request, 88 | * sending the bitcoin transaction to the server and obtaining a receipt. 89 | */ 90 | Status 91 | pay(PaymentReceipt &result, DataSlice tx, DataSlice refund); 92 | 93 | private: 94 | payments::PaymentRequest request_; 95 | payments::PaymentDetails details_; 96 | }; 97 | 98 | } // namespace abcd 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/Sweep.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_SPEND_SPEND_HPP 9 | #define ABCD_SPEND_SPEND_HPP 10 | 11 | #include "../../util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | class Wallet; 16 | 17 | /** 18 | * Sweeps the funds from an address into the wallet. 19 | * Requires that the address has been fully synced into the cache. 20 | */ 21 | void 22 | sweepOnComplete(Wallet &wallet, 23 | const std::string &address, const std::string &wif, 24 | tABC_BitCoin_Event_Callback fCallback, void *pData); 25 | 26 | } // namespace abcd 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /abcd/bitcoin/spend/paymentrequest.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Simple Bitcoin Payment Protocol messages 3 | // 4 | // Use fields 1000+ for extensions; 5 | // to avoid conflicts, register extensions via pull-req at 6 | // https://github.com/bitcoin/bips/bip-0070/extensions.mediawiki 7 | // 8 | 9 | // Edit this line to force a rebuild when updating protobuf: 3.3.0 10 | 11 | syntax = "proto2"; 12 | package payments; 13 | option java_package = "org.bitcoin.protocols.payments"; 14 | option java_outer_classname = "Protos"; 15 | option optimize_for = LITE_RUNTIME; 16 | 17 | // Generalized form of "send payment to this/these bitcoin addresses" 18 | message Output { 19 | optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis 20 | required bytes script = 2; // usually one of the standard Script forms 21 | } 22 | message PaymentDetails { 23 | optional string network = 1 [default = "main"]; // "main" or "test" 24 | repeated Output outputs = 2; // Where payment should be sent 25 | required uint64 time = 3; // Timestamp; when payment request created 26 | optional uint64 expires = 4; // Timestamp; when this request should be considered invalid 27 | optional string memo = 5; // Human-readable description of request for the customer 28 | optional string payment_url = 6; // URL to send Payment and get PaymentACK 29 | optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message 30 | } 31 | message PaymentRequest { 32 | optional uint32 payment_details_version = 1 [default = 1]; 33 | optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1 34 | optional bytes pki_data = 3; // depends on pki_type 35 | required bytes serialized_payment_details = 4; // PaymentDetails 36 | optional bytes signature = 5; // pki-dependent signature 37 | } 38 | message X509Certificates { 39 | repeated bytes certificate = 1; // DER-encoded X.509 certificate chain 40 | } 41 | message Payment { 42 | optional bytes merchant_data = 1; // From PaymentDetails.merchant_data 43 | repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs 44 | repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary 45 | optional string memo = 4; // Human-readable message for the merchant 46 | } 47 | message PaymentACK { 48 | required Payment payment = 1; // Payment message that triggered this ACK 49 | optional string memo = 2; // human-readable message for customer 50 | } 51 | -------------------------------------------------------------------------------- /abcd/crypto/Crypto.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * AirBitz cryptographic function wrappers. 10 | */ 11 | 12 | #ifndef ABCD_CRYPTO_CRYPTO_HPP 13 | #define ABCD_CRYPTO_CRYPTO_HPP 14 | 15 | #include "../util/U08Buf.hpp" 16 | #include "../../src/ABC.h" 17 | #include 18 | 19 | namespace abcd { 20 | 21 | #define AES_256_IV_LENGTH 16 22 | #define AES_256_BLOCK_LENGTH 16 23 | #define AES_256_KEY_LENGTH 32 24 | 25 | DataChunk 26 | hmacSha256(DataSlice data, DataSlice key); 27 | 28 | /** 29 | * Creates a cryptographically secure filename from a meaningful name 30 | * and a secret key. 31 | * This prevents the filename from leaking information about its contents 32 | * to anybody but the key holder. 33 | */ 34 | std::string 35 | cryptoFilename(DataSlice key, const std::string &name); 36 | 37 | tABC_CC ABC_CryptoEncryptAES256Package(DataSlice Data, 38 | DataSlice Key, 39 | tABC_U08Buf *pEncData, 40 | DataChunk &IV, 41 | tABC_Error *pError); 42 | 43 | tABC_CC ABC_CryptoDecryptAES256Package(DataChunk &result, 44 | DataSlice EncData, 45 | DataSlice Key, 46 | DataSlice IV, 47 | tABC_Error *pError); 48 | 49 | } // namespace abcd 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /abcd/crypto/Encoding.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_CRYPTO_ENCODING_HPP 9 | #define ABCD_CRYPTO_ENCODING_HPP 10 | 11 | #include "../util/Data.hpp" 12 | #include "../util/Status.hpp" 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * Encodes data into a hex string. 18 | */ 19 | std::string 20 | base16Encode(DataSlice data); 21 | 22 | /** 23 | * Decodes a hex string. 24 | */ 25 | Status 26 | base16Decode(DataChunk &result, const std::string &in); 27 | 28 | /** 29 | * Encodes data into a base-32 string according to rfc4648. 30 | */ 31 | std::string 32 | base32Encode(DataSlice data); 33 | 34 | /** 35 | * Decodes a base-32 string as defined by rfc4648. 36 | */ 37 | Status 38 | base32Decode(DataChunk &result, const std::string &in); 39 | 40 | /** 41 | * Encodes data into a base-58 string as used by Bitcoin. 42 | */ 43 | std::string 44 | base58Encode(DataSlice data); 45 | 46 | /** 47 | * Decodes a base-58 string as used by Bitcoin. 48 | */ 49 | Status 50 | base58Decode(DataChunk &result, const std::string &in); 51 | 52 | /** 53 | * Encodes data into a base-64 string according to rfc4648. 54 | */ 55 | std::string 56 | base64Encode(DataSlice data); 57 | 58 | /** 59 | * Decodes a base-64 string as defined by rfc4648. 60 | */ 61 | Status 62 | base64Decode(DataChunk &result, const std::string &in); 63 | 64 | } // namespace abcd 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /abcd/crypto/OtpKey.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "OtpKey.hpp" 9 | #include "Encoding.hpp" 10 | #include "Random.hpp" 11 | #include 12 | #include 13 | #include 14 | 15 | namespace abcd { 16 | 17 | Status 18 | OtpKey::create(size_t keySize) 19 | { 20 | ABC_CHECK(randomData(key_, keySize)); 21 | return Status(); 22 | } 23 | 24 | Status 25 | OtpKey::decodeBase32(const std::string &key) 26 | { 27 | ABC_CHECK(base32Decode(key_, key)); 28 | return Status(); 29 | } 30 | 31 | std::string 32 | OtpKey::hotp(uint64_t counter, unsigned digits) const 33 | { 34 | // Do HMAC_SHA1(key_, counter): 35 | DataArray<20> hmac; 36 | DataArray<8> cb = 37 | { 38 | { 39 | static_cast(counter >> 56), 40 | static_cast(counter >> 48), 41 | static_cast(counter >> 40), 42 | static_cast(counter >> 32), 43 | static_cast(counter >> 24), 44 | static_cast(counter >> 16), 45 | static_cast(counter >> 8), 46 | static_cast(counter) 47 | } 48 | }; 49 | HMAC(EVP_sha1(), key_.data(), key_.size(), cb.data(), cb.size(), 50 | hmac.data(), nullptr); 51 | 52 | // Calculate the truncated output: 53 | unsigned offset = hmac[19] & 0xf; 54 | uint32_t p = (hmac[offset] << 24) | (hmac[offset + 1] << 16) | 55 | (hmac[offset + 2] << 8) | hmac[offset + 3]; 56 | p &= 0x7fffffff; 57 | 58 | // Format as a fixed-width decimal number: 59 | std::stringstream ss; 60 | ss.width(digits); 61 | ss.fill('0'); 62 | ss << p; 63 | auto s = ss.str(); 64 | s.erase(0, s.size() - digits); 65 | return s; 66 | } 67 | 68 | std::string 69 | OtpKey::totp(uint64_t timeStep, unsigned digits) const 70 | { 71 | return hotp(time(nullptr) / timeStep, digits); 72 | } 73 | 74 | std::string 75 | OtpKey::encodeBase32() const 76 | { 77 | return base32Encode(key_); 78 | } 79 | 80 | } // namespace abcd 81 | -------------------------------------------------------------------------------- /abcd/crypto/OtpKey.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_CRYPTO_OTPKEY_HPP 9 | #define ABCD_CRYPTO_OTPKEY_HPP 10 | 11 | #include "../util/Data.hpp" 12 | #include "../util/Status.hpp" 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * Implements the TOTP algorithm defined by rfc6238. 18 | */ 19 | class OtpKey 20 | { 21 | public: 22 | OtpKey() {} 23 | OtpKey(DataSlice key): key_(key.begin(), key.end()) {} 24 | 25 | /** 26 | * Initializes the key with random data. 27 | */ 28 | Status 29 | create(size_t keySize=10); 30 | 31 | /** 32 | * Initializes the key with a base32-encoded string. 33 | */ 34 | Status 35 | decodeBase32(const std::string &key); 36 | 37 | /** 38 | * Produces a counter-based password. 39 | */ 40 | std::string 41 | hotp(uint64_t counter, unsigned digits=6) const; 42 | 43 | /** 44 | * Produces a time-based password. 45 | */ 46 | std::string 47 | totp(uint64_t timeStep=30, unsigned digits=6) const; 48 | 49 | /** 50 | * Encodes the key as a base32 string. 51 | */ 52 | std::string 53 | encodeBase32() const; 54 | 55 | /** 56 | * Obtains access to the underlying binary key. 57 | */ 58 | DataSlice 59 | key() const { return key_; } 60 | 61 | private: 62 | DataChunk key_; 63 | }; 64 | 65 | } // namespace abcd 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /abcd/crypto/Random.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_CRYPTO_RANDOM_HPP 9 | #define ABCD_CRYPTO_RANDOM_HPP 10 | 11 | #include "../util/Data.hpp" 12 | #include "../util/Status.hpp" 13 | 14 | namespace abcd { 15 | 16 | #define DATA_KEY_LENGTH 32 17 | #define BITCOIN_SEED_LENGTH 32 18 | 19 | /** 20 | * Sets the seed for the random number generator. 21 | */ 22 | Status 23 | randomInitialize(DataSlice seed); 24 | 25 | /** 26 | * Generates cryptographically-secure random data. 27 | */ 28 | Status 29 | randomData(DataChunk &result, size_t size); 30 | 31 | /** 32 | * Creates a random version 4 UUID. 33 | */ 34 | Status 35 | randomUuid(std::string &result); 36 | 37 | } // namespace abcd 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /abcd/crypto/Scrypt.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_CRYPTO_SCRYPT_HPP 9 | #define ABCD_CRYPTO_SCRYPT_HPP 10 | 11 | #include "../util/Data.hpp" 12 | #include "../util/Status.hpp" 13 | 14 | namespace abcd { 15 | 16 | constexpr size_t scryptDefaultSize = 32; 17 | 18 | /** 19 | * Parameters for the scrypt algorithm. 20 | */ 21 | struct ScryptSnrp 22 | { 23 | DataChunk salt; 24 | uint64_t n; 25 | uint32_t r; 26 | uint32_t p; 27 | 28 | /** 29 | * Initializes the parameters with a random salt and 30 | * benchmarked difficulty settings. 31 | */ 32 | Status 33 | create(); 34 | 35 | /** 36 | * Initialize the parameters based on a time elapsed (in microseconds) 37 | * from a 16-1-1 hash. Used to determine final hashing parameters 38 | */ 39 | void 40 | createSnrpFromTime(unsigned long totalTime); 41 | 42 | /** 43 | * The scrypt hash function. 44 | */ 45 | Status 46 | hash(DataChunk &result, DataSlice data, unsigned long *time=nullptr, 47 | size_t size=scryptDefaultSize) const; 48 | }; 49 | 50 | /** 51 | * Returns the fixed SNRP value used for the username. 52 | */ 53 | const ScryptSnrp & 54 | usernameSnrp(); 55 | 56 | } // namespace abcd 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /abcd/exchange/Currency.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Currency.hpp" 9 | #include 10 | 11 | namespace abcd { 12 | 13 | // Currency list formatters: 14 | #define CURRENCY_NUMBER_ROW(code, number, name) {{#code}, Currency::code}, 15 | #define CURRENCY_CODE_ROW(code, number, name) {Currency::code, #code}, 16 | #define CURRENCY_NAME_ROW(code, number, name) {Currency::code, name}, 17 | 18 | Status 19 | currencyNumber(Currency &result, const std::string &code) 20 | { 21 | static const std::map map 22 | { 23 | ABC_CURRENCY_LIST(CURRENCY_NUMBER_ROW) 24 | }; 25 | 26 | auto i = map.find(code); 27 | if (map.end() == i) 28 | return ABC_ERROR(ABC_CC_ParseError, "Cannot find currency code " + code); 29 | 30 | result = i->second; 31 | return Status(); 32 | } 33 | 34 | Status 35 | currencyCode(std::string &result, Currency number) 36 | { 37 | static const std::map map 38 | { 39 | ABC_CURRENCY_LIST(CURRENCY_CODE_ROW) 40 | }; 41 | 42 | auto i = map.find(number); 43 | if (map.end() == i) 44 | return ABC_ERROR(ABC_CC_ParseError, "Cannot find currency number"); 45 | 46 | result = i->second; 47 | return Status(); 48 | } 49 | 50 | Status 51 | currencyName(std::string &result, Currency number) 52 | { 53 | static const std::map map 54 | { 55 | ABC_CURRENCY_LIST(CURRENCY_NAME_ROW) 56 | }; 57 | 58 | auto i = map.find(number); 59 | if (map.end() == i) 60 | return ABC_ERROR(ABC_CC_ParseError, "Cannot find currency number"); 61 | 62 | result = i->second; 63 | return Status(); 64 | } 65 | 66 | } // namespace abcd 67 | -------------------------------------------------------------------------------- /abcd/exchange/ExchangeCache.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_EXCHANGE_EXCHANGE_CACHE_H 9 | #define ABCD_EXCHANGE_EXCHANGE_CACHE_H 10 | 11 | #include "Currency.hpp" 12 | #include "ExchangeSource.hpp" 13 | #include 14 | #include 15 | #include 16 | 17 | namespace abcd { 18 | 19 | /** 20 | * A cache for Bitcoin rates. 21 | */ 22 | class ExchangeCache 23 | { 24 | public: 25 | ExchangeCache(const std::string &path); 26 | 27 | /** 28 | * Updates the exchange rates, trying the sources in the given order. 29 | */ 30 | Status 31 | update(Currencies currencies, const ExchangeSources &sources); 32 | 33 | Status 34 | satoshiToCurrency(double &result, int64_t in, Currency currency); 35 | 36 | Status 37 | currencyToSatoshi(int64_t &result, double in, Currency currency); 38 | 39 | private: 40 | mutable std::mutex mutex_; 41 | const std::string path_; 42 | 43 | struct CacheRow 44 | { 45 | double rate; 46 | time_t timestamp; 47 | }; 48 | std::map cache_; 49 | 50 | /** 51 | * Loads the cache from disk. 52 | */ 53 | Status 54 | load(); 55 | 56 | /** 57 | * Flushes the cache to disk. 58 | */ 59 | Status 60 | save(); 61 | 62 | /** 63 | * Obtains a rate from the cache. 64 | */ 65 | Status 66 | rate(double &result, Currency currency); 67 | 68 | /** 69 | * Adds a rate to the cache. 70 | */ 71 | Status 72 | update(Currency currency, double rate, time_t now); 73 | 74 | /** 75 | * Returns true if all the listed rates are fresh in the cache. 76 | */ 77 | bool 78 | fresh(const Currencies ¤cies, time_t now); 79 | }; 80 | 81 | } // namespace abcd 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /abcd/exchange/ExchangeSource.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_EXCHANGE_EXCHANGE_SOURCE_HPP 9 | #define ABCD_EXCHANGE_EXCHANGE_SOURCE_HPP 10 | 11 | #include "Currency.hpp" 12 | #include 13 | #include 14 | 15 | namespace abcd { 16 | 17 | typedef std::list ExchangeSources; 18 | typedef std::map ExchangeRates; 19 | 20 | /** 21 | * All the exchange-rate sources implemented in the core. 22 | */ 23 | extern const ExchangeSources exchangeSources; 24 | 25 | /** 26 | * Fetches the exchange rates from a particular source. 27 | */ 28 | Status 29 | exchangeSourceFetch(ExchangeRates &result, const std::string &source); 30 | 31 | } // namespace abcd 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /abcd/http/Http.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Http.hpp" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace abcd { 16 | 17 | /** 18 | * Manages the cURL library global memory lifetime. 19 | */ 20 | struct HttpSingleton 21 | { 22 | ~HttpSingleton(); 23 | HttpSingleton(); 24 | 25 | std::unique_ptr mutexes; 26 | Status status; 27 | }; 28 | 29 | // Global variables: 30 | static HttpSingleton gSingleton; 31 | 32 | static void 33 | sslLockCallback(int mode, int n, const char *sourceFile, int sourceLine) 34 | { 35 | if (mode & CRYPTO_LOCK) 36 | gSingleton.mutexes[n].lock(); 37 | else 38 | gSingleton.mutexes[n].unlock(); 39 | } 40 | 41 | static void 42 | sslThreadIdCallback(CRYPTO_THREADID *id) 43 | { 44 | #ifdef __APPLE__ 45 | CRYPTO_THREADID_set_pointer(id, pthread_self()); 46 | #else 47 | CRYPTO_THREADID_set_numeric(id, pthread_self()); 48 | #endif 49 | } 50 | 51 | HttpSingleton::~HttpSingleton() 52 | { 53 | curl_global_cleanup(); 54 | } 55 | 56 | HttpSingleton::HttpSingleton() 57 | { 58 | // Enable SSL thread safety: 59 | mutexes.reset(new std::mutex[CRYPTO_num_locks()]); 60 | CRYPTO_set_locking_callback(sslLockCallback); 61 | CRYPTO_THREADID_set_callback(sslThreadIdCallback); 62 | 63 | // Initialize cURL: 64 | if (curl_global_init(CURL_GLOBAL_DEFAULT)) 65 | status = ABC_ERROR(ABC_CC_Error, "Cannot initialize cURL"); 66 | } 67 | 68 | Status 69 | httpInit() 70 | { 71 | return gSingleton.status; 72 | } 73 | 74 | } // namespace abcd 75 | -------------------------------------------------------------------------------- /abcd/http/Http.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_HTTP_HTTP_HPP 9 | #define ABCD_HTTP_HTTP_HPP 10 | 11 | #include "../util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | /** 16 | * Initialize the cURL library. 17 | */ 18 | Status 19 | httpInit(); 20 | 21 | } // namespace abcd 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /abcd/http/HttpRequest.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_HTTP_HTTP_REQUEST_HPP 9 | #define ABCD_HTTP_HTTP_REQUEST_HPP 10 | 11 | #include "../util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | struct HttpReply 17 | { 18 | /** The HTTP status code. */ 19 | int code; 20 | /** The returned message body. */ 21 | std::string body; 22 | 23 | /** 24 | * Verifies that the response code is in the 200 range. 25 | */ 26 | Status 27 | codeOk() const; 28 | }; 29 | 30 | /** 31 | * A class for building up and making HTTP requests. 32 | */ 33 | class HttpRequest 34 | { 35 | public: 36 | ~HttpRequest(); 37 | HttpRequest(); 38 | 39 | /** 40 | * Enables verbose debugging on the HTTP request. 41 | */ 42 | HttpRequest & 43 | debug(); 44 | 45 | /** 46 | * Adds a header to the HTTP request. 47 | */ 48 | HttpRequest & 49 | header(const std::string &key, const std::string &value); 50 | 51 | /** 52 | * Performs an HTTP GET operation. 53 | */ 54 | Status 55 | get(HttpReply &result, const std::string &url); 56 | 57 | /** 58 | * Performs an HTTP POST operation. 59 | */ 60 | Status 61 | post(HttpReply &result, const std::string &url, 62 | const std::string body=""); 63 | 64 | /** 65 | * Performs an arbitrary HTTP operation. 66 | */ 67 | Status 68 | request(HttpReply &result, const std::string &url, 69 | const char *method, const std::string body=""); 70 | 71 | protected: 72 | Status status_; 73 | CURL *handle_; 74 | 75 | private: 76 | struct curl_slist *headers_; 77 | 78 | Status init(); 79 | }; 80 | 81 | } // namespace abcd 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /abcd/http/Uri.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_UTIL_URI_HPP 9 | #define ABCD_UTIL_URI_HPP 10 | 11 | #include "../util/Status.hpp" 12 | #include 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * A parsed URI according to RFC 3986. 18 | */ 19 | class Uri 20 | { 21 | public: 22 | /** 23 | * Decodes a URI from a string. 24 | * @param strict Set to false to tolerate unescaped special characters. 25 | */ 26 | bool decode(const std::string &in, bool strict=true); 27 | std::string encode() const; 28 | 29 | /** 30 | * Returns the lowercased URI scheme. 31 | */ 32 | std::string scheme() const; 33 | void schemeSet(const std::string &scheme); 34 | 35 | /** 36 | * Obtains the unescaped authority part, if any (user@server:port). 37 | */ 38 | std::string authority() const; 39 | bool authorityOk() const; 40 | void authoritySet(const std::string &authority); 41 | void authorityRemove(); 42 | 43 | /** 44 | * Obtains the unescaped path part. 45 | */ 46 | std::string path() const; 47 | void pathSet(const std::string &path); 48 | 49 | /** 50 | * Returns the unescaped query string, if any. 51 | */ 52 | std::string query() const; 53 | bool queryOk() const; 54 | void querySet(const std::string &query); 55 | void queryRemove(); 56 | 57 | /** 58 | * Returns the unescaped fragment string, if any. 59 | */ 60 | std::string fragment() const; 61 | bool fragmentOk() const; 62 | void fragmentSet(const std::string &fragment); 63 | void fragmentRemove(); 64 | 65 | typedef std::map QueryMap; 66 | 67 | /** 68 | * Interprets the query string as a sequence of key-value pairs. 69 | * All query strings are valid, so this function cannot fail. 70 | * The results are unescaped. Both keys and values can be zero-length, 71 | * and if the same key is appears multiple times, the final one wins. 72 | */ 73 | QueryMap queryDecode() const; 74 | void queryEncode(const QueryMap &map); 75 | 76 | /** 77 | * Ensure that the URI has an authority part, 78 | * extracting it from the path if necessary. 79 | * This is useful for fixing URI's that should have a double slash 80 | * after the scheme, but don't. 81 | */ 82 | void authorize(); 83 | void deauthorize(); 84 | 85 | private: 86 | // All parts are stored with their original escaping: 87 | std::string scheme_; 88 | std::string authority_; 89 | std::string path_; 90 | std::string query_; 91 | std::string fragment_; 92 | 93 | bool authorityOk_ = false; 94 | bool queryOk_ = false; 95 | bool fragmentOk_ = false; 96 | }; 97 | 98 | } // namespace abcd 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /abcd/json/JsonArray.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "JsonArray.hpp" 9 | 10 | namespace abcd { 11 | 12 | JsonArray::JsonArray(): 13 | JsonPtr(json_array()) 14 | { 15 | } 16 | 17 | JsonArray::JsonArray(JsonPtr &&move): 18 | JsonPtr(std::move(move)) 19 | { 20 | } 21 | 22 | JsonArray::JsonArray(const JsonPtr ©): 23 | JsonPtr(copy) 24 | { 25 | } 26 | 27 | Status 28 | JsonArray::ok() 29 | { 30 | if (!json_is_array(root_)) 31 | return ABC_ERROR(ABC_CC_JSONError, "Not a JSON array."); 32 | return Status(); 33 | } 34 | 35 | JsonPtr 36 | JsonArray::operator[](size_t i) 37 | { 38 | return json_incref(json_array_get(root_, i)); 39 | } 40 | 41 | Status 42 | JsonArray::append(JsonPtr value) 43 | { 44 | if (json_array_append(root_, value.get()) < 0) 45 | return ABC_ERROR(ABC_CC_JSONError, "Cannot append to array"); 46 | return Status(); 47 | } 48 | 49 | } // namespace abcd 50 | -------------------------------------------------------------------------------- /abcd/json/JsonArray.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_JSON_JSON_ARRAY_HPP 9 | #define ABCD_JSON_JSON_ARRAY_HPP 10 | 11 | #include "JsonPtr.hpp" 12 | 13 | namespace abcd { 14 | 15 | /** 16 | * A JsonPtr with an array as it's root element. 17 | */ 18 | class JsonArray: 19 | public JsonPtr 20 | { 21 | public: 22 | JsonArray(); 23 | JsonArray(JsonPtr &&move); 24 | JsonArray(const JsonPtr ©); 25 | 26 | /** 27 | * Returns an error if this is not actually pointing to a JSON array. 28 | */ 29 | Status 30 | ok(); 31 | 32 | /** 33 | * Returns the number of values in the array. 34 | */ 35 | size_t size() { return json_array_size(root_); } 36 | 37 | /** 38 | * Retrieves a value from the array. 39 | * Returns a null value if something goes wrong. 40 | */ 41 | JsonPtr 42 | operator[](size_t i); 43 | 44 | /** 45 | * Appends a value to the end of an array. 46 | */ 47 | Status 48 | append(JsonPtr value); 49 | }; 50 | 51 | } // namespace abcd 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /abcd/json/JsonBox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "JsonBox.hpp" 9 | #include "../crypto/Crypto.hpp" 10 | #include "../crypto/Encoding.hpp" 11 | 12 | namespace abcd { 13 | 14 | enum CryptoType 15 | { 16 | AES256_CBC_AIRBITZ = 0, 17 | }; 18 | 19 | Status 20 | JsonBox::encrypt(DataSlice data, DataSlice key) 21 | { 22 | DataChunk nonce; 23 | AutoU08Buf cyphertext; 24 | ABC_CHECK_OLD(ABC_CryptoEncryptAES256Package(data, key, 25 | &cyphertext, nonce, &error)); 26 | 27 | ABC_CHECK(typeSet(AES256_CBC_AIRBITZ)); 28 | ABC_CHECK(nonceSet(base16Encode(nonce))); 29 | ABC_CHECK(cyphertextSet(base64Encode(cyphertext))); 30 | 31 | return Status(); 32 | } 33 | 34 | Status 35 | JsonBox::decrypt(DataChunk &result, DataSlice key) 36 | { 37 | DataChunk nonce; 38 | ABC_CHECK(nonceOk()); 39 | ABC_CHECK(base16Decode(nonce, this->nonce())); 40 | 41 | DataChunk cyphertext; 42 | ABC_CHECK(cyphertextOk()); 43 | ABC_CHECK(base64Decode(cyphertext, this->cyphertext())); 44 | 45 | switch (type()) 46 | { 47 | case AES256_CBC_AIRBITZ: 48 | { 49 | ABC_CHECK_OLD(ABC_CryptoDecryptAES256Package(result, 50 | cyphertext, key, nonce, 51 | &error)); 52 | return Status(); 53 | } 54 | 55 | default: 56 | return ABC_ERROR(ABC_CC_DecryptError, "Unknown encryption type"); 57 | } 58 | } 59 | 60 | } // namespace abcd 61 | -------------------------------------------------------------------------------- /abcd/json/JsonBox.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_JSON_JSON_BOX_HPP 9 | #define ABCD_JSON_JSON_BOX_HPP 10 | 11 | #include "JsonObject.hpp" 12 | #include "../util/Data.hpp" 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * A json object holding encrypted data. 18 | */ 19 | class JsonBox: 20 | public JsonObject 21 | { 22 | public: 23 | ABC_JSON_CONSTRUCTORS(JsonBox, JsonObject) 24 | 25 | /** 26 | * Puts a value into the box, encrypting it with the given key. 27 | */ 28 | Status 29 | encrypt(DataSlice data, DataSlice key); 30 | 31 | /** 32 | * Extracts the value from the box, decrypting it with the given key. 33 | */ 34 | Status 35 | decrypt(DataChunk &result, DataSlice key); 36 | 37 | private: 38 | ABC_JSON_INTEGER(type, "encryptionType", 0) 39 | ABC_JSON_STRING(nonce, "iv_hex", nullptr) 40 | ABC_JSON_STRING(cyphertext, "data_base64", nullptr) 41 | }; 42 | 43 | } // namespace abcd 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /abcd/json/JsonPtr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_JSON_JSON_PTR_HPP 9 | #define ABCD_JSON_JSON_PTR_HPP 10 | 11 | #include "../util/Status.hpp" 12 | #include "../util/Data.hpp" 13 | #include 14 | 15 | namespace abcd { 16 | 17 | /** 18 | * A json_t smart pointer. 19 | */ 20 | class JsonPtr 21 | { 22 | public: 23 | ~JsonPtr(); 24 | JsonPtr(); 25 | JsonPtr(JsonPtr &&move); 26 | JsonPtr(const JsonPtr ©); 27 | JsonPtr &operator=(const JsonPtr ©); 28 | 29 | /** 30 | * Accepts a JSON value for use as the file root. 31 | * Takes ownership of the passed-in value. 32 | */ 33 | JsonPtr(json_t *root); 34 | 35 | /** 36 | * Frees the JSON root value and replaces it with a new one. 37 | * Takes ownership of the passed-in value. 38 | */ 39 | void 40 | reset(json_t *root=nullptr); 41 | 42 | /** 43 | * Obtains the root JSON node. Do not free. 44 | */ 45 | json_t *get() const { return root_; } 46 | explicit operator bool() const { return root_; } 47 | 48 | /** 49 | * Deep-copies the contained JSON value. 50 | */ 51 | JsonPtr 52 | clone() const; 53 | 54 | /** 55 | * Loads the JSON object from disk. 56 | */ 57 | Status 58 | load(const std::string &path); 59 | 60 | /** 61 | * Loads the JSON object from disk using encryption. 62 | */ 63 | Status 64 | load(const std::string &path, DataSlice dataKey); 65 | 66 | /** 67 | * Loads the JSON object from an in-memory string. 68 | */ 69 | Status 70 | decode(const std::string &data); 71 | 72 | /** 73 | * Saves the JSON object to disk. 74 | */ 75 | Status 76 | save(const std::string &path) const; 77 | 78 | /** 79 | * Saves the JSON object to disk using encryption. 80 | */ 81 | Status 82 | save(const std::string &path, DataSlice dataKey) const; 83 | 84 | /** 85 | * Saves the JSON object to an in-memory string. 86 | */ 87 | std::string 88 | encode(bool compact=false) const; 89 | 90 | protected: 91 | json_t *root_; 92 | }; 93 | 94 | /** 95 | * Adds the standard constructors to JsonPtr child classes. 96 | */ 97 | #define ABC_JSON_CONSTRUCTORS(This, Base) \ 98 | This() {} \ 99 | This(JsonPtr &&move): Base(std::move(move)) {} \ 100 | This(const JsonPtr ©): Base(copy) {} 101 | 102 | } // namespace abcd 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /abcd/json/JsonSnrp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "JsonSnrp.hpp" 9 | #include "../crypto/Encoding.hpp" 10 | 11 | namespace abcd { 12 | 13 | Status 14 | JsonSnrp::snrpGet(ScryptSnrp &result) const 15 | { 16 | ABC_CHECK(saltOk()); 17 | ABC_CHECK(nOk()); 18 | ABC_CHECK(rOk()); 19 | ABC_CHECK(pOk()); 20 | 21 | ABC_CHECK(base16Decode(result.salt, salt())); 22 | result.n = n(); 23 | result.r = r(); 24 | result.p = p(); 25 | return Status(); 26 | } 27 | 28 | Status 29 | JsonSnrp::snrpSet(const ScryptSnrp &snrp) 30 | { 31 | ABC_CHECK(saltSet(base16Encode(snrp.salt))); 32 | ABC_CHECK(nSet(snrp.n)); 33 | ABC_CHECK(rSet(snrp.r)); 34 | ABC_CHECK(pSet(snrp.p)); 35 | return Status(); 36 | } 37 | 38 | Status 39 | JsonSnrp::create() 40 | { 41 | ScryptSnrp snrp; 42 | ABC_CHECK(snrp.create()); 43 | ABC_CHECK(snrpSet(snrp)); 44 | return Status(); 45 | } 46 | 47 | Status 48 | JsonSnrp::hash(DataChunk &result, DataSlice data) const 49 | { 50 | ScryptSnrp snrp; 51 | ABC_CHECK(snrpGet(snrp)); 52 | ABC_CHECK(snrp.hash(result, data)); 53 | return Status(); 54 | } 55 | 56 | } // namespace abcd 57 | -------------------------------------------------------------------------------- /abcd/json/JsonSnrp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_JSON_JSON_SNRP_HPP 9 | #define ABCD_JSON_JSON_SNRP_HPP 10 | 11 | #include "JsonObject.hpp" 12 | #include "../crypto/Scrypt.hpp" 13 | 14 | namespace abcd { 15 | 16 | /** 17 | * The scrypt parameter serialization format. 18 | */ 19 | struct JsonSnrp: 20 | public JsonObject 21 | { 22 | ABC_JSON_CONSTRUCTORS(JsonSnrp, JsonObject) 23 | 24 | ABC_JSON_STRING(salt, "salt_hex", nullptr) 25 | ABC_JSON_INTEGER(n, "n", 0) 26 | ABC_JSON_INTEGER(r, "r", 0) 27 | ABC_JSON_INTEGER(p, "p", 0) 28 | 29 | Status 30 | snrpGet(ScryptSnrp &result) const; 31 | 32 | Status 33 | snrpSet(const ScryptSnrp &snrp); 34 | 35 | Status 36 | create(); 37 | 38 | Status 39 | hash(DataChunk &result, DataSlice data) const; 40 | }; 41 | 42 | } // namespace abcd 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /abcd/login/Bitid.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_LOGIN_BIT_ID_HPP 9 | #define ABCD_LOGIN_BIT_ID_HPP 10 | 11 | #include "../util/Data.hpp" 12 | #include "../util/Status.hpp" 13 | #include 14 | 15 | namespace abcd { 16 | 17 | class Uri; 18 | class Wallet; 19 | 20 | /** 21 | * Extracts the callback URI from a bitid URI. 22 | */ 23 | Status 24 | bitidCallback(Uri &result, const std::string &bitidUri, bool strict=true); 25 | 26 | /** 27 | * A signed Bitid message. 28 | */ 29 | struct BitidSignature 30 | { 31 | std::string address; 32 | std::string signature; 33 | }; 34 | 35 | /** 36 | * Signs a message. 37 | * @param index allows multiple keys for the same site. 38 | */ 39 | BitidSignature 40 | bitidSign(DataSlice rootKey, const std::string &message, 41 | const std::string &callbackUri, uint32_t index=0); 42 | 43 | /** 44 | * Performs a BitID login to the specified URI. 45 | */ 46 | Status 47 | bitidLogin(DataSlice rootKey, const std::string &bitidUri, uint32_t index=0, 48 | Wallet *wallet=nullptr, const std::string &kycUri=""); 49 | 50 | } // namespace abcd 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /abcd/login/LoginPassword.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Password-based login logic. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_LOGIN_PASSWORD_HPP 13 | #define ABCD_LOGIN_LOGIN_PASSWORD_HPP 14 | 15 | #include "../util/Status.hpp" 16 | #include 17 | 18 | namespace abcd { 19 | 20 | class Login; 21 | class LoginStore; 22 | struct AuthError; 23 | 24 | /** 25 | * Loads an existing login object, either from the server or from disk. 26 | */ 27 | Status 28 | loginPassword(std::shared_ptr &result, 29 | LoginStore &store, const std::string &password, 30 | AuthError &authError); 31 | 32 | /** 33 | * Changes the password on an existing login object. 34 | */ 35 | Status 36 | loginPasswordSet(Login &login, const std::string &password); 37 | 38 | /** 39 | * Validates that the provided password is correct. 40 | * This is used in the GUI to guard access to certain actions. 41 | */ 42 | Status 43 | loginPasswordOk(bool &result, Login &login, const std::string &password); 44 | 45 | /** 46 | * Returns true if the logged-in account has a password. 47 | */ 48 | Status 49 | loginPasswordExists(bool &result, const std::string &username); 50 | 51 | } // namespace abcd 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /abcd/login/LoginPin.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * PIN-based re-login logic. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_LOGIN_PIN_HPP 13 | #define ABCD_LOGIN_LOGIN_PIN_HPP 14 | 15 | #include "../util/Status.hpp" 16 | #include 17 | #include 18 | 19 | namespace abcd { 20 | 21 | class Login; 22 | class LoginStore; 23 | struct AuthError; 24 | 25 | /** 26 | * Determines whether or not the given user can log in via PIN on this 27 | * device. 28 | */ 29 | Status 30 | loginPinExists(bool &result, const std::string &username); 31 | 32 | /** 33 | * Deletes the local copy of the PIN-based login data. 34 | */ 35 | Status 36 | loginPinDelete(LoginStore &store); 37 | 38 | /** 39 | * Assuming a PIN-based login pagage exits, log the user in. 40 | */ 41 | Status 42 | loginPin(std::shared_ptr &result, 43 | LoginStore &store, const std::string &pin, 44 | AuthError &authError); 45 | 46 | } // namespace abcd 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /abcd/login/LoginPin2.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * PIN v2 login logic. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_LOGIN_PIN_2_HPP 13 | #define ABCD_LOGIN_LOGIN_PIN_2_HPP 14 | 15 | #include "../util/Data.hpp" 16 | #include "../util/Status.hpp" 17 | #include 18 | #include 19 | 20 | namespace abcd { 21 | 22 | class AccountPaths; 23 | class Login; 24 | class LoginStore; 25 | struct AuthError; 26 | 27 | /** 28 | * Loads the pin2Key from disk, if present. 29 | */ 30 | Status 31 | loginPin2Key(DataChunk &result, const AccountPaths &paths); 32 | 33 | /** 34 | * Stashes a pin2Key on disk for future reference. 35 | */ 36 | Status 37 | loginPin2KeySave(DataSlice pin2Key, const AccountPaths &paths); 38 | 39 | /** 40 | * Creates a login object using the PJN. 41 | */ 42 | Status 43 | loginPin2(std::shared_ptr &result, 44 | LoginStore &store, DataSlice pin2Key, 45 | const std::string &pin, 46 | AuthError &authError); 47 | 48 | /** 49 | * Changes the PIN on an existing login object. 50 | */ 51 | Status 52 | loginPin2Set(DataChunk &result, Login &login, 53 | const std::string &pin); 54 | 55 | /** 56 | * Removes the PIN from the given login. 57 | */ 58 | Status 59 | loginPin2Delete(Login &login); 60 | 61 | } // namespace abcd 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /abcd/login/LoginRecovery.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Recovery-question login logic. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_LOGIN_RECOVERY_HPP 13 | #define ABCD_LOGIN_LOGIN_RECOVERY_HPP 14 | 15 | #include "../util/Status.hpp" 16 | #include 17 | 18 | namespace abcd { 19 | 20 | class Login; 21 | class LoginStore; 22 | struct AuthError; 23 | 24 | /** 25 | * Obtains the recovery questions for a user. 26 | */ 27 | Status 28 | loginRecoveryQuestions(std::string &result, LoginStore &store); 29 | 30 | /** 31 | * Creates a login object using recovery answers rather than a password. 32 | */ 33 | Status 34 | loginRecovery(std::shared_ptr &result, 35 | LoginStore &store, const std::string &recoveryAnswers, 36 | AuthError &authError); 37 | 38 | /** 39 | * Changes the recovery questions and answers on an existing login object. 40 | */ 41 | Status 42 | loginRecoverySet(Login &login, 43 | const std::string &recoveryQuestions, 44 | const std::string &recoveryAnswers); 45 | 46 | } // namespace abcd 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /abcd/login/LoginRecovery2.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Recovery-question v2 login logic. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_LOGIN_RECOVERY_2_HPP 13 | #define ABCD_LOGIN_LOGIN_RECOVERY_2_HPP 14 | 15 | #include "../util/Data.hpp" 16 | #include "../util/Status.hpp" 17 | #include 18 | #include 19 | 20 | namespace abcd { 21 | 22 | class AccountPaths; 23 | class Login; 24 | class LoginStore; 25 | struct AuthError; 26 | 27 | /** 28 | * Loads the recovery2Key from disk, if present. 29 | */ 30 | Status 31 | loginRecovery2Key(DataChunk &result, const AccountPaths &paths); 32 | 33 | /** 34 | * Stashes a recovery2Key on disk for future reference. 35 | */ 36 | Status 37 | loginRecovery2KeySave(DataSlice recovery2Key, const AccountPaths &paths); 38 | 39 | /** 40 | * Obtains the recovery questions for a user. 41 | */ 42 | Status 43 | loginRecovery2Questions(std::list &result, 44 | LoginStore &store, DataSlice recovery2Key); 45 | 46 | /** 47 | * Creates a login object using recovery answers. 48 | */ 49 | Status 50 | loginRecovery2(std::shared_ptr &result, 51 | LoginStore &store, DataSlice recovery2Key, 52 | const std::list &answers, 53 | AuthError &authError); 54 | 55 | /** 56 | * Changes the recovery questions and answers on an existing login object. 57 | */ 58 | Status 59 | loginRecovery2Set(DataChunk &result, Login &login, 60 | const std::list &questions, 61 | const std::list &answers); 62 | 63 | /** 64 | * Removes the recovery v2 questions from the given login. 65 | */ 66 | Status 67 | loginRecovery2Delete(Login &login); 68 | 69 | } // namespace abcd 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /abcd/login/LoginStore.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_LOGIN_LOGIN_STORE_HPP 9 | #define ABCD_LOGIN_LOGIN_STORE_HPP 10 | 11 | #include "../AccountPaths.hpp" 12 | #include "../crypto/OtpKey.hpp" 13 | #include "../util/Data.hpp" 14 | #include "../util/Status.hpp" 15 | #include 16 | #include 17 | 18 | namespace abcd { 19 | 20 | class OtpKey; 21 | 22 | /** 23 | * The store object contains the account data that is knowable from just 24 | * the username, without logging in. 25 | */ 26 | class LoginStore: 27 | public std::enable_shared_from_this 28 | { 29 | public: 30 | static Status 31 | create(std::shared_ptr &result, 32 | const std::string &username); 33 | 34 | /** 35 | * Obtains the normalized username for this account. 36 | */ 37 | const std::string & 38 | username() const { return username_; } 39 | 40 | /** 41 | * Obtains the paths object giving the file locations within the account. 42 | * @param create true to create the directory if it does not exist. 43 | */ 44 | Status 45 | paths(AccountPaths &result, bool create=false); 46 | 47 | /** 48 | * Obtains the hashed username used to authenticate with the server, 49 | * formerly known an L1. 50 | */ 51 | DataSlice 52 | userId() const { return userId_; } 53 | 54 | /** 55 | * Obtains the OTP key associated with this user, if any. 56 | */ 57 | const OtpKey * 58 | otpKey() const { return otpKeyOk_? &otpKey_ : nullptr; } 59 | 60 | /** 61 | * Assigns an existing OTP key to the account. 62 | */ 63 | Status 64 | otpKeySet(const OtpKey &key); 65 | 66 | /** 67 | * Removes the OTP key and deletes the file, if any. 68 | */ 69 | Status 70 | otpKeyRemove(); 71 | 72 | /** 73 | * Re-formats a username to all-lowercase, 74 | * checking for disallowed characters and collapsing spaces. 75 | */ 76 | static Status 77 | fixUsername(std::string &result, const std::string &username); 78 | 79 | private: 80 | mutable std::mutex mutex_; 81 | std::string username_; 82 | AccountPaths paths_; 83 | DataChunk userId_; 84 | 85 | bool otpKeyOk_ = false; 86 | OtpKey otpKey_; 87 | 88 | LoginStore() {}; 89 | 90 | Status 91 | init(const std::string &username); 92 | 93 | /** 94 | * Writes the OTP key to disk, assuming the account has a directory. 95 | * The caller must already be holding the mutex. 96 | */ 97 | Status 98 | otpKeySave(); 99 | }; 100 | 101 | } // namespace abcd 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /abcd/login/Otp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Otp.hpp" 9 | #include "Login.hpp" 10 | #include "LoginStore.hpp" 11 | #include "server/LoginServer.hpp" 12 | 13 | namespace abcd { 14 | 15 | Status 16 | otpAuthGet(Login &login, bool &enabled, long &timeout) 17 | { 18 | return loginServerOtpStatus(login, enabled, timeout); 19 | } 20 | 21 | Status 22 | otpAuthSet(Login &login, long timeout) 23 | { 24 | // Install a key if needed: 25 | if (!login.store.otpKey()) 26 | { 27 | OtpKey random; 28 | ABC_CHECK(random.create()); 29 | login.store.otpKeySet(random); 30 | } 31 | 32 | ABC_CHECK(loginServerOtpEnable(login, 33 | login.store.otpKey()->encodeBase32(), timeout)); 34 | 35 | return Status(); 36 | } 37 | 38 | Status 39 | otpAuthRemove(Login &login) 40 | { 41 | return loginServerOtpDisable(login); 42 | } 43 | 44 | Status 45 | otpResetGet(std::list &result, 46 | const std::list &usernames) 47 | { 48 | // List the users: 49 | std::list userIds; 50 | for (const auto &i: usernames) 51 | { 52 | std::shared_ptr store; 53 | ABC_CHECK(LoginStore::create(store, i)); 54 | auto userId = store->userId(); 55 | userIds.emplace_back(userId.begin(), userId.end()); 56 | } 57 | 58 | // Make the request: 59 | std::list flags; 60 | ABC_CHECK(loginServerOtpPending(userIds, flags)); 61 | 62 | // Smush the results: 63 | result.clear(); 64 | auto i = flags.begin(); 65 | auto j = usernames.begin(); 66 | while (i != flags.end() && j != usernames.end()) 67 | { 68 | if (*i) 69 | result.push_back(*j); 70 | ++i; 71 | ++j; 72 | } 73 | 74 | return Status(); 75 | } 76 | 77 | Status 78 | otpResetSet(LoginStore &store, const std::string &token) 79 | { 80 | return loginServerOtpReset(store, token); 81 | } 82 | 83 | Status 84 | otpResetRemove(Login &login) 85 | { 86 | return loginServerOtpResetCancelPending(login); 87 | } 88 | 89 | } // namespace abcd 90 | -------------------------------------------------------------------------------- /abcd/login/Otp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file Two-factor authentication support. 9 | */ 10 | 11 | #ifndef ABCD_LOGIN_OTP_HPP 12 | #define ABCD_LOGIN_OTP_HPP 13 | 14 | #include "../util/Data.hpp" 15 | #include "../util/Status.hpp" 16 | #include 17 | 18 | namespace abcd { 19 | 20 | class Login; 21 | class LoginStore; 22 | 23 | /** 24 | * Reads the OTP configuration from the server. 25 | */ 26 | Status 27 | otpAuthGet(Login &login, bool &enabled, long &timeout); 28 | 29 | /** 30 | * Sets up OTP authentication on the server. 31 | * 32 | * @param store The store contains the username and OTP key. 33 | * If the store has no OTP key, this function will create one. 34 | * @param timeout Reset time, in seconds. 35 | */ 36 | Status 37 | otpAuthSet(Login &login, long timeout); 38 | 39 | /** 40 | * Removes the OTP authentication requirement from the server. 41 | */ 42 | Status 43 | otpAuthRemove(Login &login); 44 | 45 | /** 46 | * Returns the reset status for a group of accounts. 47 | */ 48 | Status 49 | otpResetGet(std::list &result, 50 | const std::list &usernames); 51 | 52 | /** 53 | * Launches an OTP reset timer on the server, 54 | * which will disable the OTP authentication requirement when it expires. 55 | */ 56 | Status 57 | otpResetSet(LoginStore &store, const std::string &token); 58 | 59 | /** 60 | * Cancels an OTP reset timer. 61 | */ 62 | Status 63 | otpResetRemove(Login &login); 64 | 65 | } // namespace abcd 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /abcd/login/RecoveryQuestions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_LOGIN_RECOVERY_QUESTIONS_HPP 9 | #define ABCD_LOGIN_RECOVERY_QUESTIONS_HPP 10 | 11 | #include "../util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | void ABC_GeneralFreeQuestionChoices(tABC_QuestionChoices *pQuestionChoices); 16 | 17 | tABC_CC ABC_GeneralGetQuestionChoices(tABC_QuestionChoices **ppQuestionChoices, 18 | tABC_Error *pError); 19 | 20 | } // namespace abcd 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /abcd/login/Sharing.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_LOGIN_SHARING_HPP 9 | #define ABCD_LOGIN_SHARING_HPP 10 | 11 | #include "../util/Status.hpp" 12 | #include "../json/JsonPtr.hpp" 13 | #include 14 | 15 | namespace abcd { 16 | 17 | class Login; 18 | 19 | /** 20 | * A reference to an auth-server communications lobby. 21 | */ 22 | struct Lobby 23 | { 24 | std::string id; 25 | JsonPtr json; 26 | DataChunk requestPubkey; 27 | }; 28 | 29 | /** 30 | * Fetches a lobby from the auth server. 31 | */ 32 | Status 33 | lobbyFetch(Lobby &result, const std::string &id); 34 | 35 | /** 36 | * A login request, parsed out of a lobby. 37 | */ 38 | struct LoginRequest 39 | { 40 | std::string appId; 41 | std::string displayName; 42 | std::string displayImageUrl; 43 | }; 44 | 45 | /** 46 | * Extracts an edge-login request (if any) from the given lobby. 47 | */ 48 | Status 49 | loginRequestLoad(LoginRequest &result, const Lobby &lobby); 50 | 51 | /** 52 | * Approves the edge-login request contained in the given lobby. 53 | */ 54 | Status 55 | loginRequestApprove(Login &login, 56 | Lobby &lobby, 57 | const std::string &pin=""); 58 | 59 | } // namespace abcd 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /abcd/login/json/AuthJson.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "AuthJson.hpp" 9 | #include "LoginJson.hpp" 10 | #include "../Login.hpp" 11 | #include "../LoginStore.hpp" 12 | #include "../../crypto/Encoding.hpp" 13 | #include "../../crypto/OtpKey.hpp" 14 | 15 | namespace abcd { 16 | 17 | Status 18 | AuthJson::otpSet(const LoginStore &store) 19 | { 20 | auto otpKey = store.otpKey(); 21 | if (otpKey) 22 | ABC_CHECK(otpSet(otpKey->totp())); 23 | 24 | return Status(); 25 | } 26 | 27 | Status 28 | AuthJson::userIdSet(const LoginStore &store) 29 | { 30 | ABC_CHECK(userIdSet(base64Encode(store.userId()))); 31 | 32 | return Status(); 33 | } 34 | 35 | Status 36 | AuthJson::passwordSet(const LoginStore &store, DataSlice passwordAuth) 37 | { 38 | ABC_CHECK(otpSet(store)); 39 | ABC_CHECK(userIdSet(store)); 40 | ABC_CHECK(passwordAuthSet(base64Encode(passwordAuth))); 41 | 42 | return Status(); 43 | } 44 | 45 | Status 46 | AuthJson::pin2Set(const LoginStore &store, DataSlice pin2Id, 47 | DataSlice pin2Auth) 48 | { 49 | ABC_CHECK(otpSet(store)); 50 | ABC_CHECK(pin2IdSet(base64Encode(pin2Id))); 51 | ABC_CHECK(pin2AuthSet(base64Encode(pin2Auth))); 52 | 53 | return Status(); 54 | } 55 | 56 | Status 57 | AuthJson::recoverySet(const LoginStore &store, DataSlice recoveryAuth) 58 | { 59 | ABC_CHECK(otpSet(store)); 60 | ABC_CHECK(userIdSet(store)); 61 | ABC_CHECK(recoveryAuthSet(base64Encode(recoveryAuth))); 62 | 63 | return Status(); 64 | } 65 | 66 | Status 67 | AuthJson::recovery2Set(const LoginStore &store, DataSlice recovery2Id) 68 | { 69 | ABC_CHECK(recovery2IdSet(base64Encode(recovery2Id))); 70 | 71 | return Status(); 72 | } 73 | 74 | Status 75 | AuthJson::recovery2Set(const LoginStore &store, DataSlice recovery2Id, 76 | JsonPtr recovery2Auth) 77 | { 78 | ABC_CHECK(otpSet(store)); 79 | ABC_CHECK(recovery2IdSet(base64Encode(recovery2Id))); 80 | ABC_CHECK(recovery2AuthSet(recovery2Auth)); 81 | 82 | return Status(); 83 | } 84 | 85 | Status 86 | AuthJson::loginSet(const Login &login) 87 | { 88 | ABC_CHECK(passwordSet(login.store, login.passwordAuth())); 89 | 90 | return Status(); 91 | } 92 | 93 | Status 94 | AuthJson::stashSet(const LoginStashJson &stashJson, DataSlice loginKey) 95 | { 96 | DataChunk loginId; 97 | DataChunk loginAuth; 98 | ABC_CHECK(stashJson.loginAuthBox().decrypt(loginAuth, loginKey)); 99 | ABC_CHECK(base64Decode(loginId, stashJson.loginId())); 100 | 101 | ABC_CHECK(loginIdSet(base64Encode(loginId))); 102 | ABC_CHECK(loginAuthSet(base64Encode(loginAuth))); 103 | 104 | return Status(); 105 | } 106 | 107 | } // namespace abcd 108 | -------------------------------------------------------------------------------- /abcd/login/json/AuthJson.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * A means of authenticating with an Airbitz auth server. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_SERVER_AUTH_JSON_HPP 13 | #define ABCD_LOGIN_SERVER_AUTH_JSON_HPP 14 | 15 | #include "../../json/JsonObject.hpp" 16 | 17 | namespace abcd { 18 | 19 | class Login; 20 | class LoginStore; 21 | class LoginStashJson; 22 | 23 | /** 24 | * A proof of a user's identity for the login server. 25 | */ 26 | class AuthJson: 27 | public JsonObject 28 | { 29 | public: 30 | ABC_JSON_CONSTRUCTORS(AuthJson, JsonObject) 31 | 32 | Status 33 | otpSet(const LoginStore &store); 34 | 35 | Status 36 | userIdSet(const LoginStore &store); 37 | 38 | Status 39 | passwordSet(const LoginStore &store, DataSlice passwordAuth); 40 | 41 | Status 42 | pin2Set(const LoginStore &store, DataSlice pin2Id, 43 | DataSlice pin2Auth); 44 | 45 | Status 46 | recoverySet(const LoginStore &store, DataSlice recoveryAuth); 47 | 48 | Status 49 | recovery2Set(const LoginStore &store, DataSlice recovery2Id); 50 | 51 | Status 52 | recovery2Set(const LoginStore &store, DataSlice recovery2Id, 53 | JsonPtr recovery2Auth); 54 | 55 | Status 56 | loginSet(const Login &login); 57 | 58 | Status 59 | stashSet(const LoginStashJson &stashJson, DataSlice loginKey); 60 | 61 | protected: 62 | ABC_JSON_STRING(otp, "otp", nullptr) 63 | ABC_JSON_STRING(userId, "userId", nullptr) 64 | ABC_JSON_STRING(loginId, "loginId", nullptr) 65 | ABC_JSON_STRING(loginAuth, "loginAuth", nullptr) 66 | ABC_JSON_STRING(passwordAuth, "passwordAuth", nullptr) 67 | ABC_JSON_STRING(pin2Auth, "pin2Auth", nullptr) 68 | ABC_JSON_STRING(pin2Id, "pin2Id", nullptr) 69 | ABC_JSON_STRING(recoveryAuth, "recoveryAuth", nullptr) 70 | ABC_JSON_VALUE(recovery2Auth, "recovery2Auth", JsonPtr) 71 | ABC_JSON_STRING(recovery2Id, "recovery2Id", nullptr) 72 | }; 73 | 74 | } // namespace abcd 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /abcd/login/json/KeyJson.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_LOGIN_SERVER_KEY_JSON_HPP 9 | #define ABCD_LOGIN_SERVER_KEY_JSON_HPP 10 | 11 | #include "../../json/JsonBox.hpp" 12 | 13 | namespace abcd { 14 | 15 | constexpr auto repoTypeAirbitzAccount = "account:repo:co.airbitz.wallet"; 16 | constexpr auto keyIdLength = 32; 17 | 18 | /** 19 | * Information about an asset's keys. 20 | */ 21 | struct KeyJson: 22 | public JsonObject 23 | { 24 | ABC_JSON_CONSTRUCTORS(KeyJson, JsonObject) 25 | 26 | ABC_JSON_STRING(id, "id", nullptr) // base64 27 | ABC_JSON_STRING(type, "type", nullptr) 28 | ABC_JSON_VALUE(keys, "keys", JsonPtr) 29 | }; 30 | 31 | /** 32 | * Keys for an account settings repo. 33 | */ 34 | struct AccountRepoJson: 35 | public JsonObject 36 | { 37 | ABC_JSON_CONSTRUCTORS(AccountRepoJson, JsonObject) 38 | 39 | ABC_JSON_STRING(syncKey, "syncKey", "!bad") // base64 40 | ABC_JSON_STRING(dataKey, "dataKey", "!bad") // base64 41 | }; 42 | 43 | } // namespace abcd 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /abcd/login/json/LoginPackages.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Helper functions for dealing with login and care packages. 10 | */ 11 | 12 | #ifndef ABCD_LOGIN_LOGIN_PACKAGES_HPP 13 | #define ABCD_LOGIN_LOGIN_PACKAGES_HPP 14 | 15 | #include "../../json/JsonSnrp.hpp" 16 | #include "../../json/JsonBox.hpp" 17 | 18 | namespace abcd { 19 | 20 | /** 21 | * A round-trippable representation of the AirBitz CarePackage file. 22 | */ 23 | struct CarePackage: 24 | public JsonObject 25 | { 26 | ABC_JSON_VALUE(passwordKeySnrp, "SNRP2", JsonSnrp) 27 | ABC_JSON_VALUE(recoveryKeySnrp, "SNRP3", JsonSnrp) 28 | ABC_JSON_VALUE(questionKeySnrp, "SNRP4", JsonSnrp) 29 | ABC_JSON_VALUE(questionBox, "ERQ", JsonBox) // Optional 30 | }; 31 | 32 | /** 33 | * A round-trippable representation of the AirBitz LoginPackage file. 34 | */ 35 | struct LoginPackage: 36 | public JsonObject 37 | { 38 | ABC_JSON_VALUE(passwordBox, "EMK_LP2", JsonBox) 39 | ABC_JSON_VALUE(recoveryBox, "EMK_LRA3", JsonBox) // Optional 40 | 41 | // These are all encrypted with MK: 42 | ABC_JSON_VALUE(syncKeyBox, "ESyncKey", JsonBox) 43 | ABC_JSON_VALUE(passwordAuthBox, "ELP1", JsonBox) 44 | }; 45 | 46 | } // namespace abcd 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /abcd/login/server/AirbitzRequest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "AirbitzRequest.hpp" 9 | #include "Pinning.hpp" 10 | #include "../../Context.hpp" 11 | #include 12 | 13 | namespace abcd { 14 | 15 | static CURLcode 16 | curlSslCallback(CURL *curl, void *ssl_ctx, void *userptr) 17 | { 18 | SSL_CTX_set_verify((SSL_CTX *)ssl_ctx, 19 | SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, ABC_PinCertCallback); 20 | return CURLE_OK; 21 | } 22 | 23 | AirbitzRequest::AirbitzRequest() 24 | { 25 | if (!status_) 26 | return; 27 | 28 | // if (curl_easy_setopt(handle_, CURLOPT_SSL_CTX_FUNCTION, curlSslCallback)) 29 | // status_ = ABC_ERROR(ABC_CC_Error, "cURL failed to set SSL pinning"); 30 | header("Content-Type", "application/json"); 31 | header("Authorization", "Token " + gContext->apiKey()); 32 | } 33 | 34 | } // namespace abcd 35 | -------------------------------------------------------------------------------- /abcd/login/server/AirbitzRequest.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_HTTP_HTTP_AIRBITZ_HPP 9 | #define ABCD_HTTP_HTTP_AIRBITZ_HPP 10 | 11 | #include "../../http/HttpRequest.hpp" 12 | 13 | namespace abcd { 14 | 15 | /** 16 | * An HttpRequest with special features for talking to the Airbitz servers. 17 | * Enables certificate pinning, auth token, and "Content-Type" header. 18 | */ 19 | class AirbitzRequest: 20 | public HttpRequest 21 | { 22 | public: 23 | AirbitzRequest(); 24 | }; 25 | 26 | } // namespace abcd 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /abcd/login/server/Pinning.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * SSL certificate pinning logic. 10 | */ 11 | 12 | #ifndef ABC_PIN_h 13 | #define ABC_PIN_h 14 | 15 | #include 16 | 17 | namespace abcd { 18 | 19 | int ABC_PinCertCallback(int pok, X509_STORE_CTX *ctx); 20 | 21 | int ABC_PinPubkeyCallback(int pok, X509_STORE_CTX *ctx); 22 | 23 | } // namespace abcd 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /abcd/util/AutoFree.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_UTIL_AUTO_FREE_HPP 9 | #define ABCD_UTIL_AUTO_FREE_HPP 10 | 11 | namespace abcd { 12 | 13 | /** 14 | * A wrapper for C-style resources that need to be freed. 15 | * This is similar to the standard C++ unique_ptr, 16 | * but it is possible to mutate the underlying pointer through `get`. 17 | */ 18 | template 19 | class AutoFree 20 | { 21 | public: 22 | ~AutoFree() 23 | { 24 | if (p_) 25 | Free(p_); 26 | } 27 | 28 | AutoFree(): 29 | p_(nullptr) 30 | {} 31 | explicit AutoFree(T *p): 32 | p_(p) 33 | {} 34 | 35 | /** 36 | * Obtains a writable reference to the underlying pointer. 37 | */ 38 | T *& 39 | get() 40 | { 41 | return p_; 42 | } 43 | 44 | /** 45 | * Returns the underlying pointer, passing ownership to the caller. 46 | */ 47 | T * 48 | release() 49 | { 50 | auto out = p_; 51 | p_ = nullptr; 52 | return out; 53 | } 54 | 55 | operator T *() { return p_; } 56 | T *operator ->() { return p_; } 57 | 58 | private: 59 | T *p_; 60 | }; 61 | 62 | } // namespace abcd 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /abcd/util/Data.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Data.hpp" 9 | 10 | namespace abcd { 11 | 12 | std::string 13 | toString(DataSlice slice) 14 | { 15 | // Due to a bug, lots of AirBitz encrypted blobs end with a null byte. 16 | // Get rid of those: 17 | auto size = slice.size(); 18 | if (0 < size && !slice.data()[size - 1]) 19 | size--; 20 | 21 | return std::string(reinterpret_cast(slice.data()), size); 22 | } 23 | 24 | DataChunk 25 | buildData(std::initializer_list slices) 26 | { 27 | size_t size = 0; 28 | for (auto slice: slices) 29 | size += slice.size(); 30 | 31 | DataChunk out; 32 | out.reserve(size); 33 | for (auto slice: slices) 34 | out.insert(out.end(), slice.begin(), slice.end()); 35 | return out; 36 | } 37 | 38 | } // namespace abcd 39 | -------------------------------------------------------------------------------- /abcd/util/Data.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Helper classes for dealing with raw data. 10 | */ 11 | 12 | #ifndef ABCD_UTIL_DATA_HPP 13 | #define ABCD_UTIL_DATA_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace abcd { 21 | 22 | /** 23 | * A reference to a block of raw data. 24 | */ 25 | class DataSlice 26 | { 27 | public: 28 | DataSlice(): 29 | begin_(nullptr), end_(nullptr) 30 | {} 31 | 32 | DataSlice(const uint8_t *begin, const uint8_t *end): 33 | begin_(begin), end_(end) 34 | {} 35 | 36 | template 37 | DataSlice(const Container &container): 38 | begin_(container.data()), end_(container.data() + container.size()) 39 | {} 40 | 41 | DataSlice(const std::string &s): 42 | begin_(reinterpret_cast(s.data())), 43 | end_(reinterpret_cast(s.data()) + s.size()) 44 | {} 45 | 46 | // STL-sytle accessors: 47 | bool empty() const { return end_ == begin_; } 48 | std::size_t size() const { return end_ - begin_; } 49 | const uint8_t *data() const { return begin_; } 50 | const uint8_t *begin() const { return begin_; } 51 | const uint8_t *end() const { return end_; } 52 | 53 | private: 54 | const uint8_t *begin_; 55 | const uint8_t *end_; 56 | }; 57 | 58 | /** 59 | * Casts a data slice to a string. 60 | */ 61 | std::string 62 | toString(DataSlice slice); 63 | 64 | /** 65 | * A block of data with its size fixed at compile time. 66 | */ 67 | template using DataArray = std::array; 68 | 69 | /** 70 | * A block of data with a run-time variable size. 71 | */ 72 | typedef std::vector DataChunk; 73 | 74 | /** 75 | * Concatenates several data slices into a single buffer. 76 | */ 77 | DataChunk 78 | buildData(std::initializer_list slices); 79 | 80 | } // namespace abcd 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /abcd/util/Debug.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABC_UTIL_DEBUG_HPP 9 | #define ABC_UTIL_DEBUG_HPP 10 | 11 | #include "Status.hpp" 12 | #include "Data.hpp" 13 | 14 | #define DEBUG_LEVEL 1 15 | 16 | #define ABC_DebugLevel(level, ...) \ 17 | { \ 18 | if (DEBUG_LEVEL >= level) \ 19 | { \ 20 | ABC_DebugLog(__VA_ARGS__); \ 21 | } \ 22 | } 23 | 24 | #define ABC_Debug(level, STR) \ 25 | { \ 26 | if (DEBUG_LEVEL >= level) \ 27 | { \ 28 | logInfo(STR); \ 29 | } \ 30 | } 31 | namespace abcd { 32 | 33 | Status 34 | debugInitialize(); 35 | 36 | void 37 | debugTerminate(); 38 | 39 | DataChunk 40 | debugLogLoad(); 41 | 42 | void ABC_DebugLog(const char *format, ...); 43 | 44 | /** 45 | * Like `ABC_DebugLog`, but takes `std::string`. 46 | */ 47 | void 48 | logInfo(const std::string &message); 49 | 50 | } // namespace abcd 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /abcd/util/FileIO.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Filesystem access functions 10 | */ 11 | 12 | #ifndef ABCD_UTIL_FILE_IO_HPP 13 | #define ABCD_UTIL_FILE_IO_HPP 14 | 15 | #include "Data.hpp" 16 | #include "Status.hpp" 17 | #include 18 | 19 | namespace abcd { 20 | 21 | /** 22 | * Puts a slash on the end of a filename (if necessary). 23 | */ 24 | std::string 25 | fileSlashify(const std::string &path); 26 | 27 | /** 28 | * Returns true if a filename (without the directory part) ends with ".json". 29 | */ 30 | bool 31 | fileIsJson(const std::string &name); 32 | 33 | /** 34 | * Ensures that a directory exists, creating it if not. 35 | */ 36 | Status 37 | fileEnsureDir(const std::string &dir); 38 | 39 | /** 40 | * Returns true if the path exists. 41 | */ 42 | bool 43 | fileExists(const std::string &path); 44 | 45 | /** 46 | * Reads a file from disk. 47 | */ 48 | Status 49 | fileLoad(DataChunk &result, const std::string &path); 50 | 51 | /** 52 | * Writes a file to disk. 53 | */ 54 | Status 55 | fileSave(DataSlice data, const std::string &path); 56 | 57 | /** 58 | * Deletes a file recursively. 59 | */ 60 | Status 61 | fileDelete(const std::string &path); 62 | 63 | /** 64 | * Determines a file's last-modification time. 65 | */ 66 | Status 67 | fileTime(time_t &result, const std::string &path); 68 | 69 | } // namespace abcd 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /abcd/util/Status.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Status.hpp" 9 | #include "Debug.hpp" 10 | #include 11 | #include 12 | 13 | namespace abcd { 14 | 15 | std::ostream &operator<<(std::ostream &output, const ErrorLocation &s) 16 | { 17 | output << s.file << ":" << s.line << ": " << s.function; 18 | return output; 19 | } 20 | 21 | Status::Status() : 22 | value_(ABC_CC_Ok) 23 | { 24 | } 25 | 26 | Status::Status(tABC_CC value, std::string message, ErrorLocation here): 27 | value_(value), 28 | message_(message) 29 | { 30 | backtrace_.push_back(here); 31 | } 32 | 33 | void Status::toError(tABC_Error &error, ErrorLocation here) const 34 | { 35 | log(); 36 | 37 | error.code = value_; 38 | strncpy(error.szDescription, message_.c_str(), ABC_MAX_STRING_LENGTH); 39 | strncpy(error.szSourceFunc, here.function, ABC_MAX_STRING_LENGTH); 40 | strncpy(error.szSourceFile, here.file, ABC_MAX_STRING_LENGTH); 41 | error.nSourceLine = here.line; 42 | 43 | error.szDescription[ABC_MAX_STRING_LENGTH] = 0; 44 | error.szSourceFunc[ABC_MAX_STRING_LENGTH] = 0; 45 | error.szSourceFile[ABC_MAX_STRING_LENGTH] = 0; 46 | } 47 | 48 | Status Status::fromError(const tABC_Error &error, ErrorLocation here) 49 | { 50 | static char file[ABC_MAX_STRING_LENGTH + 1]; 51 | static char function[ABC_MAX_STRING_LENGTH + 1]; 52 | strncpy(file, error.szSourceFile, ABC_MAX_STRING_LENGTH); 53 | strncpy(function, error.szSourceFunc, ABC_MAX_STRING_LENGTH); 54 | file[ABC_MAX_STRING_LENGTH] = 0; 55 | function[ABC_MAX_STRING_LENGTH] = 0; 56 | ErrorLocation location{function, file, static_cast(error.nSourceLine)}; 57 | 58 | return Status(error.code, error.szDescription, location).at(here); 59 | } 60 | 61 | const Status & 62 | Status::log() const 63 | { 64 | if (!*this) 65 | { 66 | std::stringstream s; 67 | s << *this; 68 | ABC_DebugLog("%s", s.str().c_str()); 69 | } 70 | return *this; 71 | } 72 | 73 | Status & 74 | Status::at(ErrorLocation here) 75 | { 76 | backtrace_.push_back(here); 77 | return *this; 78 | } 79 | 80 | std::ostream &operator<<(std::ostream &output, const Status &s) 81 | { 82 | output << "Error " << s.value() << " (" << s.message() << ")"; 83 | for (const auto &i: s.backtrace()) 84 | output << std::endl << " at " << i; 85 | return output; 86 | } 87 | 88 | } // namespace abcd 89 | -------------------------------------------------------------------------------- /abcd/util/Sync.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Wrappers around the AirBitz git-sync library. 10 | */ 11 | 12 | #ifndef ABC_Sync_h 13 | #define ABC_Sync_h 14 | 15 | #include "Status.hpp" 16 | 17 | #define SYNC_KEY_LENGTH 20 18 | 19 | namespace abcd { 20 | 21 | /** 22 | * Initializes the underlying git library. 23 | * Should be called at program start. 24 | */ 25 | Status 26 | syncInit(const char *szCaCertPath); 27 | 28 | /** 29 | * Shuts down the underlying git library. 30 | * Should be called when the program exits. 31 | */ 32 | void 33 | syncTerminate(); 34 | 35 | /** 36 | * Prepares a directory for syncing. 37 | * This will create the directory if it does not exist already. 38 | * Has no effect if the repo has already been created. 39 | */ 40 | Status 41 | syncMakeRepo(const std::string &syncDir); 42 | 43 | /** 44 | * Ensure that a sync directory exists. 45 | * Has no effect if the repo has already been created. 46 | * The temporary directory allows the initial clone to happen atomically. 47 | */ 48 | Status 49 | syncEnsureRepo(const std::string &syncDir, const std::string &tempDir, 50 | const std::string &syncKey); 51 | 52 | /** 53 | * Synchronizes the directory with the server. 54 | * New files in the folder will go up to the server, 55 | * and new files on the server will come down to the directory. 56 | * If there is a conflict, the server's file will win. 57 | * @param dirty set to true if the sync has modified the filesystem, 58 | * or false otherwise. 59 | */ 60 | Status 61 | syncRepo(const std::string &syncDir, const std::string &syncKey, bool &dirty); 62 | 63 | } // namespace abcd 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /abcd/util/U08Buf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "U08Buf.hpp" 9 | #include "Util.hpp" 10 | 11 | namespace abcd { 12 | 13 | void U08BufFree(U08Buf &self) 14 | { 15 | if (self.data()) 16 | { 17 | ABC_UtilGuaranteedMemset(self.data(), 0, self.size()); 18 | free(self.data()); 19 | } 20 | self = U08Buf(); 21 | } 22 | 23 | } // namespace abcd 24 | -------------------------------------------------------------------------------- /abcd/util/Util.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Util.hpp" 9 | 10 | namespace abcd { 11 | 12 | void 13 | stringFree(char *string) 14 | { 15 | if (string) 16 | { 17 | ABC_UtilGuaranteedMemset(string, 0, strlen(string)); 18 | free(string); 19 | } 20 | } 21 | 22 | char * 23 | stringCopy(const char *string) 24 | { 25 | auto out = strdup(string); 26 | if (!out) 27 | throw std::bad_alloc(); 28 | return out; 29 | } 30 | 31 | char * 32 | stringCopy(const std::string &string) 33 | { 34 | return stringCopy(string.c_str()); 35 | } 36 | 37 | /** 38 | * For security reasons, it is important that we always make sure memory is set the way we expect 39 | * this function should ensure that 40 | * reference: http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/protect-secrets.html 41 | */ 42 | void *ABC_UtilGuaranteedMemset(void *v, int c, size_t n) 43 | { 44 | if (v) 45 | { 46 | volatile char *p = (char *)v; 47 | while (n--) 48 | { 49 | *p++ = c; 50 | } 51 | } 52 | 53 | return v; 54 | } 55 | 56 | } // namespace abcd 57 | -------------------------------------------------------------------------------- /abcd/wallet/Metadata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Metadata.hpp" 9 | #include "../json/JsonObject.hpp" 10 | #include "../util/Util.hpp" 11 | 12 | namespace abcd { 13 | 14 | struct MetadataJson: 15 | public JsonObject 16 | { 17 | ABC_JSON_CONSTRUCTORS(MetadataJson, JsonObject); 18 | ABC_JSON_STRING(name, "name", ""); 19 | ABC_JSON_STRING(category, "category", ""); 20 | ABC_JSON_STRING(notes, "notes", ""); 21 | ABC_JSON_INTEGER(bizId, "bizId", 0); 22 | ABC_JSON_NUMBER(amountCurrency, "amountCurrency", 0); 23 | 24 | // Obsolete/moved fields: 25 | ABC_JSON_INTEGER(attributes, "attributes", 0); 26 | ABC_JSON_INTEGER(amount, "amountSatoshi", 0); 27 | ABC_JSON_INTEGER(minerFee, "amountFeeMinersSatoshi", 0); 28 | ABC_JSON_INTEGER(airbitzFee, "amountFeeAirBitzSatoshi", 0); 29 | }; 30 | 31 | Metadata::Metadata(): 32 | bizId(0), 33 | amountCurrency(0) 34 | { 35 | } 36 | 37 | Metadata::Metadata(const tABC_TxDetails *pDetails): 38 | name(pDetails->szName ? pDetails->szName : ""), 39 | category(pDetails->szCategory ? pDetails->szCategory : ""), 40 | notes(pDetails->szNotes ? pDetails->szNotes : ""), 41 | bizId(pDetails->bizId), 42 | amountCurrency (pDetails->amountCurrency) 43 | { 44 | } 45 | 46 | Status 47 | Metadata::load(const JsonObject &json) 48 | { 49 | MetadataJson metaJson(json); 50 | name = metaJson.name(); 51 | category = metaJson.category(); 52 | notes = metaJson.notes(); 53 | bizId = metaJson.bizId(); 54 | amountCurrency = metaJson.amountCurrency(); 55 | return Status(); 56 | } 57 | 58 | Status 59 | Metadata::save(JsonObject &json) const 60 | { 61 | MetadataJson metaJson(json); 62 | ABC_CHECK(metaJson.nameSet(name)); 63 | ABC_CHECK(metaJson.categorySet(category)); 64 | ABC_CHECK(metaJson.notesSet(notes)); 65 | ABC_CHECK(metaJson.bizIdSet(bizId)); 66 | ABC_CHECK(metaJson.amountCurrencySet(amountCurrency)); 67 | 68 | // Obsolete/moved fields: 69 | ABC_CHECK(metaJson.attributesSet(0)); 70 | ABC_CHECK(metaJson.amountSet(0)); 71 | ABC_CHECK(metaJson.minerFeeSet(0)); 72 | ABC_CHECK(metaJson.airbitzFeeSet(0)); 73 | return Status(); 74 | } 75 | 76 | tABC_TxDetails * 77 | Metadata::toDetails() const 78 | { 79 | tABC_TxDetails *out = structAlloc(); 80 | out->szName = stringCopy(name); 81 | out->szCategory = stringCopy(category); 82 | out->szNotes = stringCopy(notes); 83 | out->bizId = bizId; 84 | out->amountCurrency = amountCurrency; 85 | out->amountSatoshi = 0; 86 | out->amountFeesAirbitzSatoshi = 0; 87 | out->amountFeesMinersSatoshi = 0; 88 | return out; 89 | } 90 | 91 | } // namespace abcd 92 | -------------------------------------------------------------------------------- /abcd/wallet/Metadata.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_WALLET_METADATA_HPP 9 | #define ABCD_WALLET_METADATA_HPP 10 | 11 | #include "../util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | class JsonObject; 16 | 17 | /** 18 | * Common user-editable metadata for transactions and addresses. 19 | */ 20 | struct Metadata 21 | { 22 | Metadata(); 23 | Metadata(const tABC_TxDetails *pDetails); 24 | 25 | // User-editable metadata: 26 | std::string name; 27 | std::string category; 28 | std::string notes; 29 | unsigned bizId; 30 | double amountCurrency; 31 | 32 | /** 33 | * Loads the structure from a JSON object. 34 | */ 35 | Status 36 | load(const JsonObject &json); 37 | 38 | /** 39 | * Writes the structure fields into the provided JSON object. 40 | */ 41 | Status 42 | save(JsonObject &json) const; 43 | 44 | /** 45 | * Converts this structure to the legacy format. 46 | */ 47 | tABC_TxDetails * 48 | toDetails() const; 49 | }; 50 | 51 | } // namespace abcd 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /abcd/wallet/Receive.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_WALLET_RECEIVE_HPP 9 | #define ABCD_WALLET_RECEIVE_HPP 10 | 11 | #include "../util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | struct TxInfo; 16 | class Wallet; 17 | 18 | /** 19 | * Updates the wallet when a new transaction comes in from the network. 20 | */ 21 | Status 22 | onReceive(Wallet &wallet, const TxInfo &info, 23 | tABC_BitCoin_Event_Callback fCallback, void *pData); 24 | 25 | } // namespace abcd 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /abcd/wallet/TxDb.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef ABCD_WALLET_TX_DB_HPP 9 | #define ABCD_WALLET_TX_DB_HPP 10 | 11 | #include "../json/JsonPtr.hpp" 12 | #include "../util/Status.hpp" 13 | #include "Metadata.hpp" 14 | #include 15 | #include 16 | #include 17 | 18 | namespace abcd { 19 | 20 | class Wallet; 21 | 22 | struct TxMeta 23 | { 24 | std::string ntxid; 25 | std::string txid; 26 | time_t timeCreation; 27 | bool internal; 28 | uint64_t airbitzFeeWanted = 0; // The fee owed for this transaction 29 | int64_t airbitzFeeSent = 0; // The fee actually sent 30 | Metadata metadata; 31 | }; 32 | 33 | /** 34 | * Manages the transaction metadata stored in the wallet sync directory. 35 | */ 36 | class TxDb 37 | { 38 | public: 39 | TxDb(const Wallet &wallet); 40 | 41 | /** 42 | * Loads the transactions off disk. 43 | */ 44 | Status 45 | load(); 46 | 47 | /** 48 | * Updates a particular transaction in the database. 49 | * Can also be used to insert new transactions into the database. 50 | */ 51 | Status 52 | save(const TxMeta &tx, int64_t balance, int64_t fee); 53 | 54 | /** 55 | * Looks up a particular transaction in the database. 56 | */ 57 | Status 58 | get(TxMeta &result, const std::string &ntxid); 59 | 60 | /** 61 | * Determine how many satoshis of unpaid Airbitz fees are in the wallet. 62 | */ 63 | int64_t 64 | airbitzFeePending(); 65 | 66 | /** 67 | * Determine the last time the wallet sent out Airbitz fees. 68 | */ 69 | time_t 70 | airbitzFeeLastSent(); 71 | 72 | /** 73 | * Get all known txs 74 | */ 75 | std::map 76 | getTxs(); 77 | 78 | private: 79 | mutable std::mutex mutex_; 80 | const Wallet &wallet_; 81 | const std::string dir_; 82 | 83 | std::map txs_; 84 | std::map files_; 85 | 86 | std::string 87 | path(const TxMeta &tx); 88 | }; 89 | 90 | } // namespace abcd 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /astyle-options: -------------------------------------------------------------------------------- 1 | --style=allman 2 | --attach-namespaces 3 | --attach-extern-c 4 | --align-pointer=name 5 | --align-reference=name 6 | --keep-one-line-blocks 7 | --max-code-length=80 8 | --lineend=linux 9 | -------------------------------------------------------------------------------- /cli/Command.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "Command.hpp" 9 | #include 10 | #include 11 | 12 | Command::~Command() 13 | { 14 | } 15 | 16 | typedef std::map CommandMap; 17 | 18 | // Implementing this by value would be dangerous, 19 | // since we can't ensure its constructor runs before ours. 20 | // We create this on the heap when we need it, which ensures it exists. 21 | std::unique_ptr gMap; 22 | 23 | CommandRegistry::CommandRegistry(const char *name, Command *c) 24 | { 25 | if (!gMap) 26 | gMap.reset(new CommandMap); 27 | 28 | if (gMap->end() != gMap->find(name)) 29 | std::cerr << "warning: Duplicate command " << name << std::endl; 30 | 31 | (*gMap)[name] = c; 32 | } 33 | 34 | Command * 35 | CommandRegistry::find(const std::string &name) 36 | { 37 | if (!gMap) 38 | return nullptr; 39 | 40 | auto i = gMap->find(name); 41 | if (gMap->end() == i) 42 | return nullptr; 43 | 44 | return i->second; 45 | } 46 | 47 | void 48 | CommandRegistry::print() 49 | { 50 | if (!gMap) 51 | return; 52 | 53 | for (auto &i: *gMap) 54 | std::cout << i.second->name() << std::endl; 55 | } 56 | 57 | std::string 58 | helpString(const Command &command) 59 | { 60 | std::string out = "usage: abc-cli"; 61 | 62 | if (InitLevel::context <= command.level()) 63 | out += " [-d ] [-a ]"; 64 | 65 | if (InitLevel::store <= command.level()) 66 | out += " [-u ]"; 67 | 68 | if (InitLevel::login <= command.level()) 69 | out += " [-p ]"; 70 | 71 | if (InitLevel::wallet <= command.level()) 72 | out += " [-w ]"; 73 | 74 | return out + " " + command.name() + command.help(); 75 | } 76 | -------------------------------------------------------------------------------- /cli/abc-cli-bash-completion.sh: -------------------------------------------------------------------------------- 1 | # abc-cli bash-completion (Airbitz command line client - airbitz.co) 2 | 3 | _abc_cli_complete() 4 | { 5 | local cur_word prev_word type_list 6 | 7 | # COMP_WORDS is an array of words in the current command line. 8 | # COMP_CWORD is the index of the current word (the one the cursor is 9 | # in). So COMP_WORDS[COMP_CWORD] is the current word; we also record 10 | # the previous word here, although this specific script doesn't 11 | # use it yet. 12 | cur_word="${COMP_WORDS[COMP_CWORD]}" 13 | prev_word="${COMP_WORDS[COMP_CWORD-1]}" 14 | 15 | # Ask abc-cli to generate a list of types it supports 16 | type_list='account-available 17 | account-create 18 | account-decrypt 19 | account-encrypt 20 | account-list 21 | account-sync 22 | address-allocate 23 | address-calculate 24 | address-list 25 | address-search 26 | bitid-login 27 | bitid-sign 28 | category-add 29 | category-list 30 | category-remove 31 | change-password 32 | change-password-recovery 33 | check-password 34 | check-recovery-answers 35 | exchange-fetch 36 | exchange-update 37 | exchange-validate 38 | general-update 39 | get-question-choices 40 | get-questions 41 | hiddenbits-generate 42 | otp-auth-get 43 | otp-auth-remove 44 | otp-auth-set 45 | otp-key-get 46 | otp-key-remove 47 | otp-key-set 48 | otp-reset-get 49 | otp-reset-remove 50 | pin-login 51 | pin-login-setup 52 | plugin-clear 53 | plugin-get 54 | plugin-keys 55 | plugin-list 56 | plugin-remove 57 | plugin-set 58 | repo-clone 59 | repo-sync 60 | settings-get 61 | settings-set-nickname 62 | settings-set-recovery-reminder 63 | sign-in 64 | spend-address 65 | spend-airbitz-fee 66 | spend-bip70 67 | spend-get-fee 68 | spend-get-max 69 | spend-transfer 70 | stratum-version 71 | upload-logs 72 | version 73 | wallet-archive 74 | wallet-create 75 | wallet-decrypt 76 | wallet-encrypt 77 | wallet-info 78 | wallet-list 79 | wallet-order 80 | wallet-remove 81 | wallet-seed 82 | wallet-sync 83 | watcher' 84 | 85 | # COMPREPLY is the array of possible completions, generated with 86 | # the compgen builtin. 87 | if [[ ${prev_word} == 'abc-cli' ]] ; then 88 | COMPREPLY=( $(compgen -W "${type_list}" -- ${cur_word}) ) 89 | else 90 | COMPREPLY=() 91 | fi 92 | return 0 93 | } 94 | 95 | # Register _pss_complete to provide completion for the following commands 96 | complete -F _abc_cli_complete abc-cli 97 | -------------------------------------------------------------------------------- /cli/airbitz.conf: -------------------------------------------------------------------------------- 1 | { 2 | "apiKey": "", 3 | "chainKey": "", 4 | "hiddenBitsKey": "", 5 | "workingDir": "/home/lucas/tmp/airbitz_cli/", 6 | "username": "", 7 | "password": "", 8 | "wallet": "" 9 | } 10 | -------------------------------------------------------------------------------- /cli/commands/Bitid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/http/Uri.hpp" 10 | #include "../../abcd/login/Bitid.hpp" 11 | #include "../../abcd/login/Login.hpp" 12 | 13 | using namespace abcd; 14 | 15 | COMMAND(InitLevel::login, BitidLogin, "bitid-login", 16 | " ") 17 | { 18 | if (argc != 1) 19 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 20 | const auto uri = argv[0]; 21 | 22 | Uri callback; 23 | ABC_CHECK(bitidCallback(callback, uri, false)); 24 | callback.pathSet(""); 25 | std::cout << "Signing in to " << callback.encode() << std::endl; 26 | 27 | bitidLogin(session.login->rootKey(), uri, 0); 28 | 29 | return Status(); 30 | } 31 | 32 | COMMAND(InitLevel::login, BitidAddressSignature, "bitid-sign", 33 | " []") 34 | { 35 | if (argc < 2 || 3 < argc) 36 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 37 | const auto uri = argv[0]; 38 | const auto message = argv[1]; 39 | int index = argc == 3 ? atoi(argv[2]) : 0; 40 | 41 | Uri callback; 42 | ABC_CHECK(bitidCallback(callback, uri, false)); 43 | const auto signature = bitidSign(session.login->rootKey(), 44 | message, callback.encode(), index); 45 | 46 | std::cout << "Address: " << signature.address << std::endl; 47 | std::cout << "Signature: " << signature.signature << std::endl; 48 | 49 | return Status(); 50 | } 51 | -------------------------------------------------------------------------------- /cli/commands/Categories.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/account/AccountCategories.hpp" 10 | #include 11 | 12 | using namespace abcd; 13 | 14 | COMMAND(InitLevel::account, CategoryList, "category-list", 15 | "") 16 | { 17 | if (argc != 0) 18 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 19 | 20 | AccountCategories categories; 21 | ABC_CHECK(accountCategoriesLoad(categories, *session.account)); 22 | for (const auto &category: categories) 23 | std::cout << category << std::endl; 24 | 25 | return Status(); 26 | } 27 | 28 | COMMAND(InitLevel::account, CategoryAdd, "category-add", 29 | " ") 30 | { 31 | if (argc != 1) 32 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 33 | const auto category = argv[0]; 34 | 35 | ABC_CHECK(accountCategoriesAdd(*session.account, category)); 36 | return Status(); 37 | } 38 | 39 | COMMAND(InitLevel::account, CategoryRemove, "category-remove", 40 | " ") 41 | { 42 | if (argc != 1) 43 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 44 | const auto category = argv[0]; 45 | 46 | ABC_CHECK(accountCategoriesRemove(*session.account, category)); 47 | return Status(); 48 | } 49 | -------------------------------------------------------------------------------- /cli/commands/Commands.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/General.hpp" 10 | #include "../../abcd/login/LoginPassword.hpp" 11 | #include "../../abcd/util/Util.hpp" 12 | #include 13 | 14 | using namespace abcd; 15 | 16 | COMMAND(InitLevel::login, ChangePassword, "change-password", 17 | " ") 18 | { 19 | if (argc != 1) 20 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 21 | const auto newPassword = argv[0]; 22 | 23 | ABC_CHECK_OLD(ABC_ChangePassword(session.username.c_str(), 24 | session.password.c_str(), 25 | newPassword, &error)); 26 | 27 | return Status(); 28 | } 29 | 30 | COMMAND(InitLevel::context, CheckPassword, "check-password", 31 | " ") 32 | { 33 | if (argc != 1) 34 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 35 | const auto password = argv[0]; 36 | 37 | double secondsToCrack; 38 | unsigned int count = 0; 39 | tABC_PasswordRule **aRules = NULL; 40 | ABC_CHECK_OLD(ABC_CheckPassword(password, &secondsToCrack, &aRules, &count, 41 | &error)); 42 | 43 | for (unsigned i = 0; i < count; ++i) 44 | { 45 | printf("%s: %d\n", aRules[i]->szDescription, aRules[i]->bPassed); 46 | } 47 | printf("Time to Crack: %f\n", secondsToCrack); 48 | ABC_FreePasswordRuleArray(aRules, count); 49 | 50 | return Status(); 51 | } 52 | 53 | COMMAND(InitLevel::context, GeneralUpdate, "general-update", 54 | "") 55 | { 56 | if (argc != 0) 57 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 58 | 59 | ABC_CHECK(generalUpdate()); 60 | 61 | return Status(); 62 | } 63 | 64 | COMMAND(InitLevel::login, SignIn, "sign-in", 65 | "") 66 | { 67 | if (argc != 0) 68 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 69 | 70 | return Status(); 71 | } 72 | 73 | COMMAND(InitLevel::account, UploadLogs, "upload-logs", 74 | "") 75 | { 76 | if (argc != 0) 77 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 78 | 79 | // TODO: Command non-functional without a watcher thread! 80 | ABC_CHECK_OLD(ABC_UploadLogs(session.username.c_str(), 81 | session.password.c_str(), &error)); 82 | 83 | return Status(); 84 | } 85 | 86 | COMMAND(InitLevel::none, Version, "version", 87 | "") 88 | { 89 | if (argc != 0) 90 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 91 | 92 | AutoString version; 93 | ABC_CHECK_OLD(ABC_Version(&version.get(), &error)); 94 | std::cout << "ABC version: " << version.get() << std::endl; 95 | return Status(); 96 | } 97 | -------------------------------------------------------------------------------- /cli/commands/Hiddenbits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/bitcoin/Text.hpp" 10 | #include 11 | 12 | using namespace abcd; 13 | 14 | COMMAND(InitLevel::context, CliGenerateHiddenbits, "hiddenbits-generate", 15 | " []") 16 | { 17 | if (0 != argc && 1 != argc) 18 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 19 | 20 | long count = 1; 21 | if (1 == argc) 22 | count = atol(argv[0]); 23 | 24 | for (long i = 0; i < count; ++i) 25 | { 26 | std::string key; 27 | std::string address; 28 | ABC_CHECK(hbitsCreate(key, address)); 29 | std::cout << key << " " << address << std::endl; 30 | } 31 | 32 | return Status(); 33 | } 34 | -------------------------------------------------------------------------------- /cli/commands/Lobby.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/login/Sharing.hpp" 10 | #include "../../abcd/util/Util.hpp" 11 | #include 12 | 13 | using namespace abcd; 14 | 15 | COMMAND(InitLevel::context, LobbyGet, "lobby-get", 16 | " ") 17 | { 18 | if (argc != 1) 19 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 20 | auto id = argv[0]; 21 | 22 | Lobby lobby; 23 | ABC_CHECK(lobbyFetch(lobby, id)); 24 | 25 | std::cout << "Contents:" << std::endl; 26 | LoginRequest request; 27 | if (loginRequestLoad(request, lobby)) 28 | { 29 | std::cout << " Account request:" << std::endl; 30 | std::cout << " appId:\t" << request.appId << std::endl; 31 | std::cout << " name:\t" << request.displayName << std::endl; 32 | std::cout << " image:\t" << request.displayImageUrl << std::endl; 33 | } 34 | else 35 | { 36 | std::cout << " " << lobby.json.encode() << std::endl; 37 | } 38 | 39 | return Status(); 40 | } 41 | 42 | COMMAND(InitLevel::account, LobbyApproveEdge, "lobby-approve-edge", 43 | " ") 44 | { 45 | if (argc != 1) 46 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 47 | auto id = argv[0]; 48 | 49 | // Get PIN: 50 | AutoFree pSettings; 51 | ABC_CHECK_OLD(ABC_LoadAccountSettings(session.username.c_str(), 52 | session.password.c_str(), 53 | &pSettings.get(), &error)); 54 | auto pin = pSettings->szPIN ? pSettings->szPIN : ""; 55 | 56 | Lobby lobby; 57 | ABC_CHECK(lobbyFetch(lobby, id)); 58 | ABC_CHECK(loginRequestApprove(*session.login, lobby, pin)); 59 | 60 | return Status(); 61 | } 62 | -------------------------------------------------------------------------------- /cli/commands/Pin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/login/server/LoginServer.hpp" 10 | #include "../../src/LoginShim.hpp" 11 | #include 12 | 13 | using namespace abcd; 14 | 15 | COMMAND(InitLevel::store, PinLogin, "pin-login", 16 | " ") 17 | { 18 | if (argc != 1) 19 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 20 | const auto pin = argv[0]; 21 | 22 | bool exists; 23 | ABC_CHECK_OLD(ABC_PinLoginExists(session.username.c_str(), 24 | &exists, &error)); 25 | if (!exists) 26 | return ABC_ERROR(ABC_CC_PinExpired, "PIN login is not present"); 27 | 28 | AuthError authError; 29 | auto s = cacheLoginPin(session.login, 30 | session.username.c_str(), 31 | pin, 32 | authError); 33 | if (authError.pinWait) 34 | std::cout << "Please try again in " << authError.pinWait 35 | << " seconds" << std::endl; 36 | ABC_CHECK(s); 37 | 38 | return Status(); 39 | } 40 | 41 | COMMAND(InitLevel::account, PinLoginSetup, "pin-login-setup", 42 | " ") 43 | { 44 | if (1 != argc) 45 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 46 | const auto pin = argv[0]; 47 | 48 | ABC_CHECK_OLD(ABC_PinSetup(session.username.c_str(), 49 | session.password.c_str(), 50 | pin, &error)); 51 | 52 | return Status(); 53 | } 54 | -------------------------------------------------------------------------------- /cli/commands/Recovery.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/login/LoginPassword.hpp" 10 | #include "../../abcd/login/LoginRecovery.hpp" 11 | #include "../../abcd/login/server/LoginServer.hpp" 12 | #include "../../abcd/util/Util.hpp" 13 | #include 14 | 15 | using namespace abcd; 16 | 17 | COMMAND(InitLevel::store, RecoveryQuestions, "recovery-questions", 18 | "") 19 | { 20 | if (argc != 0) 21 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 22 | 23 | AutoString questions; 24 | ABC_CHECK_OLD(ABC_GetRecoveryQuestions(session.username.c_str(), 25 | &questions.get(), &error)); 26 | printf("Questions: %s\n", questions.get()); 27 | 28 | return Status(); 29 | } 30 | 31 | COMMAND(InitLevel::context, RecoveryQuestionChoices, 32 | "recovery-question-choices", 33 | "") 34 | { 35 | if (argc != 0) 36 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 37 | 38 | AutoFree pChoices; 39 | ABC_CHECK_OLD(ABC_GetQuestionChoices(&pChoices.get(), &error)); 40 | 41 | printf("Choices:\n"); 42 | for (unsigned i = 0; i < pChoices->numChoices; ++i) 43 | { 44 | printf(" %s (%s, %d)\n", pChoices->aChoices[i]->szQuestion, 45 | pChoices->aChoices[i]->szCategory, 46 | pChoices->aChoices[i]->minAnswerLength); 47 | } 48 | 49 | return Status(); 50 | } 51 | 52 | COMMAND(InitLevel::store, RecoveryLogin, "recovery-login", 53 | " ") 54 | { 55 | if (argc != 1) 56 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 57 | const auto answers = argv[0]; 58 | 59 | AuthError authError; 60 | std::shared_ptr login; 61 | ABC_CHECK(loginRecovery(login, *session.store, answers, authError)); 62 | 63 | return Status(); 64 | } 65 | 66 | COMMAND(InitLevel::store, RecoveryChangePassword, "recovery-change-password", 67 | " ") 68 | { 69 | if (argc != 2) 70 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 71 | const auto answers = argv[0]; 72 | const auto newPassword = argv[1]; 73 | 74 | AuthError authError; 75 | std::shared_ptr login; 76 | ABC_CHECK(loginRecovery(login, *session.store, answers, authError)); 77 | ABC_CHECK(loginPasswordSet(*login, newPassword)); 78 | 79 | return Status(); 80 | } 81 | 82 | COMMAND(InitLevel::login, RecoverySetup, "recovery-setup", 83 | " ") 84 | { 85 | if (argc != 2) 86 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 87 | const auto questions = argv[0]; 88 | const auto answers = argv[1]; 89 | 90 | ABC_CHECK(loginRecoverySet(*session.login, questions, answers)); 91 | 92 | return Status(); 93 | } 94 | -------------------------------------------------------------------------------- /cli/commands/Repo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/Context.hpp" 10 | #include "../../abcd/util/Sync.hpp" 11 | #include 12 | 13 | using namespace abcd; 14 | 15 | static std::string 16 | repoPath(const std::string &key) 17 | { 18 | return gContext->paths.rootDir() + "repo-" + key; 19 | } 20 | 21 | COMMAND(InitLevel::context, RepoClone, "repo-clone", 22 | " ") 23 | { 24 | if (argc != 1) 25 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 26 | const auto key = argv[0]; 27 | 28 | const auto path = repoPath(key); 29 | const auto tempPath = path + "-tmp"; 30 | ABC_CHECK(syncEnsureRepo(path, tempPath, key)); 31 | 32 | return Status(); 33 | } 34 | 35 | COMMAND(InitLevel::context, RepoSync, "repo-sync", 36 | " ") 37 | { 38 | if (argc != 1) 39 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 40 | const auto key = argv[0]; 41 | 42 | bool dirty; 43 | const auto path = repoPath(key); 44 | ABC_CHECK(syncRepo(path, key, dirty)); 45 | 46 | if (dirty) 47 | std::cout << "Contents changed" << std::endl; 48 | else 49 | std::cout << "No changes" << std::endl; 50 | 51 | return Status(); 52 | } 53 | -------------------------------------------------------------------------------- /cli/commands/Stratum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../Command.hpp" 9 | #include "../../abcd/bitcoin/network/StratumConnection.hpp" 10 | #include 11 | #include 12 | 13 | using namespace abcd; 14 | 15 | static int done = 0; 16 | 17 | COMMAND(InitLevel::context, CliStratumVersion, "stratum-version", 18 | " ") 19 | { 20 | if (1 != argc) 21 | return ABC_ERROR(ABC_CC_Error, helpString(*this)); 22 | const auto uri = argv[0]; 23 | 24 | // Connect to the server: 25 | StratumConnection c; 26 | ABC_CHECK(c.connect(uri)); 27 | std::cout << "Connection established" << std::endl; 28 | 29 | // Send the version command: 30 | auto onError = [](Status status) 31 | { 32 | std::cout << "Got error " << status << std::endl; 33 | ++done; 34 | }; 35 | auto onReply = [](const std::string &version) 36 | { 37 | std::cout << "Version: " << version << std::endl; 38 | ++done; 39 | return Status(); 40 | }; 41 | c.version(onError, onReply); 42 | 43 | // Main loop: 44 | while (true) 45 | { 46 | SleepTime sleep; 47 | ABC_CHECK(c.wakeup(sleep)); 48 | if (1 <= done) 49 | break; 50 | 51 | zmq_pollitem_t pollitem = 52 | { 53 | nullptr, c.pollfd(), ZMQ_POLLIN, ZMQ_POLLOUT 54 | }; 55 | long timeout = sleep.count() ? sleep.count() : -1; 56 | zmq_poll(&pollitem, 1, timeout); 57 | } 58 | 59 | return Status(); 60 | } 61 | -------------------------------------------------------------------------------- /cli/doc/.gitignore: -------------------------------------------------------------------------------- 1 | abc-cli.1 2 | abc-cli.html 3 | -------------------------------------------------------------------------------- /cli/doc/README.md: -------------------------------------------------------------------------------- 1 | ### The ABC-CLI documentation 2 | 3 | Please adjust the abc-cli.pod file, the abc-cli-bash-completion.sh and regenerate the man and html files if you change the CLI. 4 | 5 | #### pod2man 6 | Create a new man page: 7 | ``` 8 | pod2man cli/doc/abc-cli.pod cli/doc/abc-cli.1 9 | ``` 10 | View the man page: man cli/doc/abc-cli.1 11 | 12 | See: http://perldoc.perl.org/pod2man.html 13 | 14 | #### pod2html 15 | Create a new HTML page: 16 | ``` 17 | pod2html --infile=cli/doc/abc-cli.pod --outfile=cli/doc/abc-cli.html --noindex 18 | ``` 19 | See: http://perldoc.perl.org/pod2html.html 20 | -------------------------------------------------------------------------------- /deps/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /build-testnet 3 | /download 4 | -------------------------------------------------------------------------------- /deps/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR ?= build 2 | 3 | default: abc 4 | 5 | $(BUILD_DIR)/%/tasks.mk: recipes/% 6 | @ ./run.sh $* write-tasks 7 | -include $(patsubst recipes/%,$(BUILD_DIR)/%/tasks.mk,$(wildcard recipes/*)) 8 | 9 | clean: 10 | rm -rf $(BUILD_DIR) 11 | -------------------------------------------------------------------------------- /deps/abc-cli: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | build_dir=${BUILD_DIR:-$(pwd)/build} 3 | touch ./recipes/abc/abc.recipe 4 | make abc.build-native && ( cd ..; $build_dir/abc/native/abc-cli "$@" ) 5 | -------------------------------------------------------------------------------- /deps/abc-watcher: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | build_dir=${BUILD_DIR:-$(pwd)/build} 3 | make abc.build-native && ( cd ..; $build_dir/abc/native/abc-watcher "$@" ) 4 | -------------------------------------------------------------------------------- /deps/classes/android: -------------------------------------------------------------------------------- 1 | inherit common 2 | 3 | # Builds a library using the Andorid NDK. 4 | # $1 arch name for toolchain, work_dir and install_dir. 5 | # $2 cross-compiler prefix. 6 | build_android() { 7 | # Put the source in the working directory: 8 | work_dir=$work_dir/android-$1 9 | mkdir -p $work_dir 10 | unpack 11 | 12 | # Establish expected variables: 13 | target=android-$1 14 | install_dir=$build_dir/prefix/android/$1 15 | 16 | cross=$2 17 | export AR="${cross}-ar" 18 | export AS="${cross}-as" 19 | export CC="${cross}-clang" 20 | export CCLD="${cross}-clang" 21 | export CPP="${cross}-clang -E" 22 | export CXX="${cross}-clang++" 23 | export LD="${cross}-ld" 24 | export NM="${cross}-nm" 25 | export OBJCOPY="${cross}-objcopy" 26 | export OBJDUMP="${cross}-objdump" 27 | export RANLIB="${cross}-ranlib" 28 | export STRINGS="${cross}-strings" 29 | export STRIP="${cross}-strip" 30 | 31 | export CFLAGS="-isystem${install_dir}/include -fPIC -O2" 32 | export CXXFLAGS="-isystem${install_dir}/include -fPIC -O2" 33 | export LDFLAGS="-L${install_dir}/lib -fPIC" 34 | 35 | if [ $1 = "arm" ]; then 36 | export CFLAGS="$CFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb" 37 | export CXXFLAGS="$CXXFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb" 38 | export LDFLAGS="$LDFLAGS -march=armv7-a -Wl,--fix-cortex-a8" 39 | fi 40 | 41 | export PATH=$build_dir/ndk/$1/bin:$PATH 42 | export PKG_CONFIG_PATH=$install_dir/lib/pkgconfig 43 | 44 | cd $work_dir 45 | build 46 | } 47 | build_android_arm() { 48 | build_android arm arm-linux-androideabi 49 | } 50 | build_android_x86() { 51 | build_android x86 i686-linux-android 52 | } 53 | build_android_mips() { 54 | build_android mips mipsel-linux-android 55 | } 56 | 57 | for arch in arm x86 mips; do 58 | deps="download ndk.setup-$arch" 59 | for dep in $depends; do 60 | deps="$deps $dep.build-android-$arch" 61 | done 62 | task build-android-$arch $deps 63 | done 64 | default=build-android-arm 65 | -------------------------------------------------------------------------------- /deps/classes/android.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Linux) 2 | set(CMAKE_SYSTEM_VERSION 1) 3 | 4 | # Where is the target environment: 5 | set(CMAKE_FIND_ROOT_PATH "${CMAKE_INSTALL_PREFIX}") 6 | 7 | # Search for programs in the build host directories: 8 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 9 | 10 | # Search for libraries and headers in the target directories: 11 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 13 | -------------------------------------------------------------------------------- /deps/classes/common: -------------------------------------------------------------------------------- 1 | # Common variables 2 | download_dir=${DOWNLOAD_DIR:-$base_dir/download} 3 | 4 | # Common tasks 5 | 6 | # Downloads all the source files mentioned in $source 7 | download() { 8 | mkdir -p $download_dir 9 | for s in $source; do 10 | url=${s%#*} # Remove hash part 11 | path=$download_dir/${url##*/} 12 | path=${path%%\?*} # Remove query part 13 | hash=${s##*#} 14 | hash=${hash%"$url"} 15 | 16 | # Download: 17 | if [ $path != ${path%.git} ]; then 18 | if [ -e "$path" ]; then 19 | git --git-dir="$path" fetch -f "$url" +refs/heads/*:refs/heads/* 20 | else 21 | git clone --bare "$url" "$path" 22 | fi 23 | else 24 | if [ ! -e "$path" ]; then 25 | curl -L "$url" > "$path" 26 | fi 27 | 28 | # Checksum: 29 | output=$(shasum "$path") 30 | output="${output%% *}" 31 | if [ -n "$hash" -a "$hash" != "$output" ]; then 32 | echo "error: checksum failed on $(relative path): expected $hash, got $output" 33 | echo "moving $(relative $path) to $(relative $path).fail" 34 | mv "$path" "$path.fail" 35 | return 1 36 | else 37 | echo "SHA1 $(relative $path) = $output" 38 | fi 39 | fi 40 | done 41 | } 42 | task download 43 | 44 | # Unpacks the source files mentioned in $source with the .tar.* extension 45 | unpack() { 46 | for s in $source; do 47 | url=${s%#*} # Remove hash part 48 | path=$download_dir/${url##*/} 49 | path=${path%%\?*} # Remove query part 50 | hash=${s##*#} 51 | hash=${hash%"$url"} 52 | 53 | # Unpack: 54 | if [ $path != ${path%.git} ]; then 55 | git --git-dir="$path" --work-tree="$work_dir" reset --hard "${hash:-master}" 56 | elif [ $path != ${path%.tar*} -o $path != ${path%.tgz} ]; then 57 | echo "Unpacking $(relative $path) to $(relative $work_dir)..." 58 | tar -C "$work_dir" -xmf "$path" 59 | fi 60 | done 61 | } 62 | task unpack download 63 | 64 | # Writes the full (recursive) dependency list for a package 65 | write_deps() { 66 | for dep in $depends; do 67 | echo $dep 68 | cat $build_dir/$dep/depends 69 | done | sort | uniq > depends 70 | } 71 | task write-deps $(for dep in $depends; do echo $dep.write-deps; done) 72 | 73 | clean() { 74 | rm -rf $work_dir 75 | } 76 | task clean 77 | -------------------------------------------------------------------------------- /deps/classes/ios.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Darwin) 2 | set(CMAKE_SYSTEM_VERSION 1) 3 | 4 | # Where is the target environment: 5 | set(CMAKE_FIND_ROOT_PATH "${CMAKE_INSTALL_PREFIX}") 6 | 7 | # Search for programs in the build host directories: 8 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 9 | 10 | # Search for libraries and headers in the target directories: 11 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 13 | -------------------------------------------------------------------------------- /deps/classes/lib: -------------------------------------------------------------------------------- 1 | inherit android 2 | if [ Darwin = $(uname -s) ]; then 3 | inherit osx 4 | inherit ios 5 | fi 6 | inherit native 7 | -------------------------------------------------------------------------------- /deps/classes/native: -------------------------------------------------------------------------------- 1 | inherit common 2 | 3 | # Builds a library using the native tools 4 | build_native() { 5 | # Put the source in the working directory: 6 | work_dir=$work_dir/native 7 | mkdir -p $work_dir 8 | unpack 9 | 10 | # Establish expected variables: 11 | target=native 12 | install_dir=$build_dir/prefix/native/$1 13 | cross="" 14 | 15 | export AR=ar 16 | export CC=clang 17 | export CXX="clang++" 18 | 19 | export CFLAGS="-g -fPIC -I${install_dir}/include" 20 | export CXXFLAGS="-g -fPIC -I${install_dir}/include" 21 | export LDFLAGS="-L${install_dir}/lib" 22 | 23 | export PKG_CONFIG_PATH="$install_dir/lib/pkgconfig:$install_dir/lib64/pkgconfig" 24 | 25 | cd $work_dir 26 | build 27 | } 28 | 29 | deps="download" 30 | for dep in $depends; do 31 | deps="$deps $dep.build-native" 32 | done 33 | task build-native $deps 34 | default=build-native 35 | -------------------------------------------------------------------------------- /deps/classes/native.cmake: -------------------------------------------------------------------------------- 1 | # Where is the target environment: 2 | set(CMAKE_FIND_ROOT_PATH "${CMAKE_INSTALL_PREFIX}") 3 | 4 | # Search for programs in the build host directories: 5 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 6 | 7 | # Search for libraries and headers in the target directories: 8 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 9 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 10 | -------------------------------------------------------------------------------- /deps/classes/osx.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Darwin) 2 | set(CMAKE_SYSTEM_VERSION 1) 3 | 4 | # Where is the target environment: 5 | set(CMAKE_FIND_ROOT_PATH "${CMAKE_INSTALL_PREFIX}") 6 | 7 | # Search for programs in the build host directories: 8 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 9 | 10 | # Search for libraries and headers in the target directories: 11 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 13 | -------------------------------------------------------------------------------- /deps/make-testnet: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make BUILD_DIR=${BUILD_DIR:-build}-testnet ENABLE_TESTNET=1 $@ 3 | -------------------------------------------------------------------------------- /deps/mk-abc-only: -------------------------------------------------------------------------------- 1 | touch recipes/abc 2 | make abc 3 | -------------------------------------------------------------------------------- /deps/recipes/abc/abc.recipe: -------------------------------------------------------------------------------- 1 | depends="curl jansson libbitcoin libcsv libgit2 libqrencode openssl protobuf zeromq" 2 | inherit lib 3 | 4 | build() { 5 | cd $base_dir/.. 6 | export WORK_DIR=$work_dir 7 | 8 | case $target in 9 | android-*) output=libabc.so ;; 10 | *) output=libabc.a ;; 11 | esac 12 | 13 | export CFLAGS="$CFLAGS -O2" 14 | export CXXFLAGS="$CXXFLAGS -O2" 15 | 16 | # Build: 17 | make $output V=1 18 | 19 | # Native builds include unit tests and utilities: 20 | if [ $target = native ]; then 21 | make all V=1 22 | fi 23 | 24 | # Install: 25 | mkdir -p $install_dir/lib 26 | cp $work_dir/$output $install_dir/lib 27 | cp src/ABC.h $install_dir/include 28 | } 29 | 30 | clean() { 31 | cd $base_dir/.. 32 | export WORK_DIR=$work_dir 33 | make clean 34 | } 35 | 36 | tar() { 37 | cd $base_dir/.. 38 | export WORK_DIR=$work_dir/native 39 | make tar V=1 40 | } 41 | task tar build-native 42 | 43 | lib="lib/libabc.a" 44 | include="include/ABC.h" 45 | -------------------------------------------------------------------------------- /deps/recipes/boost/boost.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | version="1_62_0" 4 | source="https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_$version.tar.bz2#5fd97433c3f859d8cbab1eaed4156d3068ae3648" 5 | 6 | build() { 7 | LIBRARIES=--with-libraries=chrono,date_time,filesystem,locale,program_options,regex,system,thread 8 | 9 | cd boost_$version 10 | 11 | echo Patching boost... 12 | patch -p1 < $recipe_dir/fix-asio-android.patch 13 | cp $recipe_dir/user-config.jam tools/build/src/user-config.jam 14 | 15 | echo Bootstrapping boost... 16 | ./bootstrap.sh --prefix=$install_dir $LIBRARIES 17 | 18 | echo Building boost... 19 | export NO_BZIP2=1 20 | ./bjam -q -d+2 toolset=gcc-env link=static threading=multi install 21 | } 22 | 23 | include="include/boost/*" 24 | lib="lib/libboost_*.a" 25 | -------------------------------------------------------------------------------- /deps/recipes/boost/fix-asio-android.patch: -------------------------------------------------------------------------------- 1 | --- a/boost/config/user.hpp 2 | +++ b/boost/config/user.hpp 3 | @@ -131,3 +131,5 @@ 4 | // to ensure the correct libraries are selected at link time. 5 | // #define BOOST_LIB_BUILDID amd64 6 | 7 | +#define BOOST_ASIO_DISABLE_SERIAL_PORT 1 8 | + 9 | -------------------------------------------------------------------------------- /deps/recipes/boost/user-config.jam: -------------------------------------------------------------------------------- 1 | import os ; 2 | local AR = [ os.environ AR ] ; 3 | local CXX = [ os.environ CXX ] ; 4 | local CFLAGS = [ os.environ CFLAGS ] ; 5 | local RANLIB = [ os.environ RANLIB ] ; 6 | 7 | # We aren't necessarily using GCC, but the "gcc" toolchain lets us specify 8 | # our own binaries for everything. The final toolchain name is "gcc-env": 9 | using gcc : env : $(CXX) : 10 | $(AR) 11 | $(RANLIB) 12 | $(CFLAGS) 13 | -fvisibility=hidden 14 | -fvisibility-inlines-hidden 15 | -fdata-sections 16 | -D_REENTRANT 17 | -D_GLIBCXX__PTHREADS 18 | ; 19 | -------------------------------------------------------------------------------- /deps/recipes/curl/curl.recipe: -------------------------------------------------------------------------------- 1 | depends="openssl" 2 | inherit lib 3 | 4 | version="7.50.3" 5 | source="http://curl.haxx.se/download/curl-$version.tar.gz#be0065afc76a3d8568f5f78d8efddadb6310f9d7" 6 | 7 | build() { 8 | cd curl-$version 9 | 10 | ./configure --enable-static --disable-shared \ 11 | --enable-ipv6 \ 12 | --disable-ldap --without-libssh2 --without-librtmp --without-libidn \ 13 | --host=$cross --prefix=$install_dir 14 | make 15 | make install 16 | } 17 | 18 | include="include/curl/*" 19 | lib="lib/libcurl.a" 20 | -------------------------------------------------------------------------------- /deps/recipes/jansson/jansson.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | version="2.7" 4 | source="www.digip.org/jansson/releases/jansson-$version.tar.bz2#51cd3b57f152132de686bb8c1f4471cc9ca7970e" 5 | 6 | build() { 7 | cd jansson-$version 8 | autoreconf -i 9 | ./configure --enable-static --disable-shared --host=$cross --prefix=$install_dir 10 | make 11 | make install 12 | } 13 | 14 | include="include/jansson.h include/jansson_config.h" 15 | lib="lib/libjansson.a" 16 | -------------------------------------------------------------------------------- /deps/recipes/libbitcoin/config.patch: -------------------------------------------------------------------------------- 1 | diff --git a/configure.ac b/configure.ac 2 | index c1a2121..ddf1c21 100644 3 | --- a/configure.ac 4 | +++ b/configure.ac 5 | @@ -212,12 +212,7 @@ AC_SUBST([pthread_LIBS], [-lpthread]) 6 | 7 | # Require rt if on linux and output ${rt_LIBS}. 8 | #------------------------------------------------------------------------------ 9 | -AS_CASE([${host_os}], [*linux*], 10 | - [AC_CHECK_LIB([rt], [clock_gettime], 11 | - [AC_SUBST([rt_LIBS], [-lrt]) 12 | - AC_MSG_NOTICE([rt_LIBS : ${rt_LIBS}])], 13 | - [AC_MSG_ERROR([rt library is required but was not found.])])], 14 | - [AC_SUBST([rt_LIBS], [])]) 15 | +AC_SUBST([rt_LIBS], []) 16 | 17 | # Require icu-i18n of at least version 51.2 and output ${icu_i18n_CPPFLAGS/LIBS/PKG}. 18 | #------------------------------------------------------------------------------ 19 | -------------------------------------------------------------------------------- /deps/recipes/libbitcoin/libbitcoin.recipe: -------------------------------------------------------------------------------- 1 | depends="boost libsecp256k1" 2 | inherit lib 3 | 4 | source="https://github.com/libbitcoin/libbitcoin.git#7a1a9d43" 5 | 6 | build() { 7 | echo Patching... 8 | patch -p1 < $recipe_dir/config.patch 9 | 10 | echo Building... 11 | autoreconf -i 12 | ./configure --enable-static --disable-shared --host=$cross --prefix=$install_dir \ 13 | --without-tests --without-examples ${ENABLE_TESTNET:+--enable-testnet} --with-boost-libdir=$install_dir/lib 14 | make 15 | make install 16 | } 17 | 18 | include="include/bitcoin/*" 19 | lib="lib/libbitcoin.a" 20 | -------------------------------------------------------------------------------- /deps/recipes/libcsv/libcsv.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | version="3.0.3" 4 | source="http://tenet.dl.sourceforge.net/project/libcsv/libcsv/libcsv-$version/libcsv-$version.tar.gz#2f637343c3dfac80559595f519e8f78f25acc7c1" 5 | 6 | build() { 7 | cd libcsv-$version 8 | ./configure --enable-static --disable-shared --host=$cross --prefix=$install_dir 9 | make 10 | make install 11 | } 12 | 13 | include="include/csv.h" 14 | lib="lib/libcsv.a" 15 | -------------------------------------------------------------------------------- /deps/recipes/libgit2/ios-build.patch: -------------------------------------------------------------------------------- 1 | commit b14a2a3aea59b7f1821e118e43eba4efc2a5d6f1 2 | Author: William Swanson 3 | Date: Thu Nov 5 16:05:38 2015 -0800 4 | 5 | ios-build.patch 6 | 7 | diff --git a/CMakeLists.txt b/CMakeLists.txt 8 | index 73c9630..bb92e34 100644 9 | --- a/CMakeLists.txt 10 | +++ b/CMakeLists.txt 11 | @@ -39,9 +39,13 @@ OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) 12 | OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF ) 13 | OPTION( VALGRIND "Configure build for valgrind" OFF ) 14 | OPTION( CURL "User curl for HTTP if available" ON) 15 | +OPTION( USE_OPENSSL "Link with and use openssl library" ON ) 16 | 17 | IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 18 | SET( USE_ICONV ON ) 19 | +ENDIF() 20 | + 21 | +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT USE_OPENSSL) 22 | FIND_PACKAGE(Security) 23 | FIND_PACKAGE(CoreFoundation REQUIRED) 24 | ENDIF() 25 | @@ -76,10 +80,6 @@ IF(MSVC) 26 | OPTION(MSVC_CRTDBG "Enable CRTDBG memory leak reporting" OFF) 27 | ENDIF() 28 | 29 | -IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 30 | - OPTION( USE_OPENSSL "Link with and use openssl library" ON ) 31 | -ENDIF() 32 | - 33 | # This variable will contain the libraries we need to put into 34 | # libgit2.pc's Requires.private. That is, what we're linking to or 35 | # what someone who's statically linking us needs to link to. 36 | @@ -459,7 +459,8 @@ 37 | ENDIF() 38 | 39 | CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS) 40 | -IF (HAVE_FUTIMENS) 41 | + 42 | +IF (HAVE_FUTIMENS AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 43 | ADD_DEFINITIONS(-DHAVE_FUTIMENS) 44 | ENDIF () 45 | 46 | @@ -534,8 +535,10 @@ 47 | 48 | # Compile and link libgit2 49 | ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC}) 50 | -TARGET_LINK_LIBRARIES(git2 ${SECURITY_DIRS}) 51 | -TARGET_LINK_LIBRARIES(git2 ${COREFOUNDATION_DIRS}) 52 | +IF (SECURITY_FOUND AND COREFOUNDATION_FOUND) 53 | + TARGET_LINK_LIBRARIES(git2 ${SECURITY_DIRS}) 54 | + TARGET_LINK_LIBRARIES(git2 ${COREFOUNDATION_DIRS}) 55 | +ENDIF() 56 | TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES}) 57 | TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES}) 58 | TARGET_LINK_LIBRARIES(git2 ${GSSAPI_LIBRARIES}) 59 | -------------------------------------------------------------------------------- /deps/recipes/libgit2/libgit2.recipe: -------------------------------------------------------------------------------- 1 | depends="openssl curl" 2 | inherit lib 3 | 4 | version="0.23.4" 5 | source="https://github.com/libgit2/libgit2/archive/v$version.tar.gz#02ff3374da7fdf116984adf41749db7b4d0a5877" 6 | 7 | build() { 8 | cd "libgit2-$version" 9 | 10 | case $target in 11 | ios-*) cmakeflags="-DCMAKE_TOOLCHAIN_FILE=$recipe_dir/../../classes/ios.toolchain.cmake" ;; 12 | android-*) cmakeflags="-DCMAKE_TOOLCHAIN_FILE=$recipe_dir/../../classes/android.toolchain.cmake -DANDROID=1" ;; 13 | *) cmakeflags="-C$recipe_dir/../../classes/native.cmake" ;; 14 | esac 15 | 16 | echo Patching... 17 | patch -p1 < $recipe_dir/ios-build.patch 18 | patch -p1 < $recipe_dir/timeout.patch 19 | 20 | mkdir -p build 21 | cd build 22 | cmake .. $cmakeflags \ 23 | -DCMAKE_INSTALL_PREFIX=$install_dir \ 24 | -DBUILD_SHARED_LIBS:BOOL=FALSE \ 25 | -DBUILD_CLAR:BOOL=FALSE \ 26 | -DUSE_OPENSSL:BOOL=TRUE \ 27 | -DUSE_SSH:BOOL=FALSE 28 | make 29 | make install 30 | } 31 | 32 | include="include/git2.h include/git/*" 33 | lib="lib/libgit2.a" 34 | -------------------------------------------------------------------------------- /deps/recipes/libgit2/timeout.patch: -------------------------------------------------------------------------------- 1 | commit 90a3f31976ef0ac1436d80003a83a3db055e9e88 2 | Author: William Swanson 3 | Date: Thu Nov 5 16:27:12 2015 -0800 4 | 5 | timeout.patch 6 | 7 | diff --git a/src/curl_stream.c b/src/curl_stream.c 8 | index ca06c20..d96c93a 100644 9 | --- a/src/curl_stream.c 10 | +++ b/src/curl_stream.c 11 | @@ -35,6 +35,8 @@ static int curls_connect(git_stream *stream) 12 | long sockextr; 13 | int failed_cert = 0; 14 | CURLcode res; 15 | + 16 | + curl_easy_setopt(s->handle, CURLOPT_CONNECTTIMEOUT, 10); 17 | res = curl_easy_perform(s->handle); 18 | 19 | if (res != CURLE_OK && res != CURLE_PEER_FAILED_VERIFICATION) 20 | diff --git a/src/socket_stream.c b/src/socket_stream.c 21 | index 71f4911..7411b85 100644 22 | --- a/src/socket_stream.c 23 | +++ b/src/socket_stream.c 24 | @@ -68,6 +68,40 @@ static int close_socket(GIT_SOCKET s) 25 | 26 | } 27 | 28 | +static 29 | +int timeout_connect(int sock, struct sockaddr *addr, 30 | + socklen_t addr_len, struct timeval *tv) 31 | +{ 32 | + fd_set fdset; 33 | + int flags = 0; 34 | + int so_error; 35 | + socklen_t len = sizeof(so_error); 36 | + 37 | + if ((flags = fcntl(sock, F_GETFL, 0)) < 0) 38 | + return -1; 39 | + 40 | + if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) 41 | + return -1; 42 | + 43 | + if (connect(sock, addr, addr_len) == 0) 44 | + goto exit; 45 | + 46 | + FD_ZERO(&fdset); 47 | + FD_SET(sock, &fdset); 48 | + 49 | + if (select(sock + 1, NULL, &fdset, NULL, tv) > 0) 50 | + { 51 | + getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len); 52 | + if (so_error == 0) 53 | + goto exit; 54 | + } 55 | + return -1; 56 | +exit: 57 | + if (fcntl(sock, F_SETFL, flags) < 0) 58 | + return -1; 59 | + return 0; 60 | +} 61 | + 62 | int socket_connect(git_stream *stream) 63 | { 64 | struct addrinfo *info = NULL, *p; 65 | @@ -76,6 +110,10 @@ int socket_connect(git_stream *stream) 66 | GIT_SOCKET s = INVALID_SOCKET; 67 | int ret; 68 | 69 | + struct timeval sto; 70 | + sto.tv_sec = 10; 71 | + sto.tv_usec = 0; 72 | + 73 | #ifdef GIT_WIN32 74 | /* on win32, the WSA context needs to be initialized 75 | * before any socket calls can be performed */ 76 | @@ -111,7 +149,7 @@ int socket_connect(git_stream *stream) 77 | break; 78 | } 79 | 80 | - if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0) 81 | + if (timeout_connect(s, p->ai_addr, (socklen_t)p->ai_addrlen, &sto) == 0) 82 | break; 83 | 84 | /* If we can't connect, try the next one */ 85 | -------------------------------------------------------------------------------- /deps/recipes/libqrencode/libqrencode.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | version="3.4.4" 4 | source="http://megaui.net/fukuchi/works/qrencode/qrencode-$version.tar.bz2#6de54316081e5528e415b250730dcddbfdaa4b0e" 5 | 6 | build() { 7 | cd qrencode-$version 8 | 9 | echo Patching... 10 | rm use/config.sub 11 | mkdir -p m4 12 | grep -v -e AM_PATH_SDL -e AM_ICONV_LINK configure.ac > configure.ac.new 13 | mv configure.ac.new configure.ac 14 | ./autogen.sh 15 | 16 | echo Building... 17 | ./configure --enable-static --disable-shared --host=$cross --without-tools --prefix=$install_dir 18 | make 19 | make install 20 | } 21 | 22 | include="include/qrencode.h" 23 | lib="lib/libqrencode.a" 24 | -------------------------------------------------------------------------------- /deps/recipes/libsecp256k1/libsecp256k1.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | source="https://github.com/libbitcoin/secp256k1.git#22f60a62" 4 | 5 | build() { 6 | # Optimize: 7 | patch -p1 < $recipe_dir/optimize.patch 8 | 9 | # Build: 10 | autoreconf -i 11 | ./configure --enable-static --disable-shared --host=$cross --prefix=$install_dir \ 12 | --disable-tests --with-bignum=no --with-field=32bit 13 | make clean 14 | make 15 | make install 16 | } 17 | 18 | include="include/secp256k1.h" 19 | lib="lib/libsecp256k1.a" 20 | -------------------------------------------------------------------------------- /deps/recipes/libsecp256k1/optimize.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h 2 | index 1b2856f..0e786d7 100644 3 | --- a/src/ecmult_impl.h 4 | +++ b/src/ecmult_impl.h 5 | @@ -18,10 +18,10 @@ 6 | exponentially larger precomputed tables. */ 7 | #ifdef USE_ENDOMORPHISM 8 | /** Two tables for window size 15: 1.375 MiB. */ 9 | -#define WINDOW_G 15 10 | +#define WINDOW_G 11 11 | #else 12 | /** One table for window size 16: 1.375 MiB. */ 13 | -#define WINDOW_G 16 14 | +#define WINDOW_G 12 15 | #endif 16 | 17 | /** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table. 18 | -------------------------------------------------------------------------------- /deps/recipes/libsodium/libsodium.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | version="1.0.3" 4 | source="https://github.com/jedisct1/libsodium/releases/download/$version/libsodium-$version.tar.gz#e44ed485842966d4e2d8f58e74a5fd78fbfbe4b0" 5 | 6 | build() { 7 | cd libsodium-$version 8 | ./autogen.sh 9 | ./configure --enable-static --disable-shared --host=$cross --prefix=$install_dir 10 | make 11 | make install 12 | } 13 | 14 | include="include/sodium.h include/sodium/*" 15 | lib="lib/libsodium.a" 16 | -------------------------------------------------------------------------------- /deps/recipes/ndk/langinfo.h: -------------------------------------------------------------------------------- 1 | /* Android is missing these symbols for some reason, 2 | * so pick a reasonable approximation: */ 3 | #ifndef RADIXCHAR 4 | #define RADIXCHAR MON_DECIMAL_POINT 5 | #endif 6 | 7 | #ifndef THOUSEP 8 | #define THOUSEP MON_THOUSANDS_SEP 9 | #endif 10 | -------------------------------------------------------------------------------- /deps/recipes/ndk/ndk.recipe: -------------------------------------------------------------------------------- 1 | # This recipe contains the setup tasks for unpacking and installing the NDK 2 | inherit common 3 | 4 | version="r13b" 5 | 6 | # Select the correct NDK version for the host system: 7 | case $(uname -sm) in 8 | "Linux x86_64") 9 | system=linux-x86_64 10 | source="https://dl.google.com/android/repository/android-ndk-$version-$system.zip#0600157c4ddf50ec15b8a037cfc474143f718fd0" ;; 11 | "Darwin x86_64") 12 | system=darwin-x86_64 13 | source="https://dl.google.com/android/repository/android-ndk-$version-$system.zip#71fe653a7bf5db08c3af154735b6ccbc12f0add5" ;; 14 | *) 15 | echo "Unknown host platform!" 16 | exit 1;; 17 | esac 18 | 19 | # Extracts a standalone toolchain from the NDK. 20 | # $1 arch name for installing the toolchain. 21 | # $2 NDK toolchain name. 22 | setup() { 23 | echo Unpacking NDK... 24 | archive="$download_dir/android-ndk-$version-$system.zip" 25 | unzip -o -d"$work_dir" $archive 26 | 27 | echo Unpacking toolchain... 28 | cd android-ndk-$version 29 | python build/tools/make_standalone_toolchain.py --verbose --arch $1 --api 14 --stl libc++ --force --install-dir $work_dir/$1 30 | 31 | echo Patching headers... 32 | cat $recipe_dir/langinfo.h >> $work_dir/$1/sysroot/usr/local/include/langinfo.h 33 | } 34 | setup_arm() { 35 | setup arm arm-linux-androideabi 36 | } 37 | setup_x86() { 38 | setup x86 x86 39 | } 40 | setup_mips() { 41 | setup mips mipsel-linux-android 42 | } 43 | 44 | task setup-arm download 45 | task setup-x86 download 46 | task setup-mips download 47 | default=setup-arm 48 | -------------------------------------------------------------------------------- /deps/recipes/openssl/openssl.recipe: -------------------------------------------------------------------------------- 1 | depends="zlib" 2 | inherit lib 3 | 4 | version="1.0.2j" 5 | source="https://www.openssl.org/source/openssl-$version.tar.gz#bdfbdb416942f666865fa48fe13c2d0e588df54f" 6 | 7 | build() { 8 | cd openssl-$version 9 | 10 | # Configure: 11 | if [ $target = "native" ]; then 12 | if [ 'Darwin x86_64 i386' = "$(uname -smp)" ]; then 13 | # The openssl configure script won't auto-detect Darwin x64: 14 | ./Configure --prefix=$install_dir no-shared zlib darwin64-x86_64-cc "$CFLAGS" 15 | else 16 | # Otherwise, let the config script guess: 17 | ./config --prefix=$install_dir "$CFLAGS" 18 | fi 19 | else 20 | # We are cross-compiling, so specify the target manually: 21 | case $target in 22 | osx-x86_64) type=darwin64-x86_64-cc ;; 23 | ios-x86_64) type=darwin64-x86_64-cc ;; 24 | ios-i386) type=debug-darwin-i386-cc ;; 25 | ios-*) type=BSD-generic32 ;; 26 | *) type=gcc ;; 27 | esac 28 | ./Configure --prefix=$install_dir no-shared zlib $type -DOPENSSL_THREADS "$CFLAGS" 29 | fi 30 | 31 | make 32 | make install_sw 33 | } 34 | 35 | include="include/openssl/*" 36 | lib="lib/libcrypto.a lib/libssl.a" 37 | -------------------------------------------------------------------------------- /deps/recipes/protobuf/protobuf.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | # When changing this, also edit abcd/bitcoin/spend/paymentrequest.proto 4 | # to force a re-build. 5 | 6 | version="3.5.1" 7 | source="https://github.com/google/protobuf/releases/download/v$version/protobuf-cpp-$version.tar.gz#c63ba5e9c737abf83aa2b3f86229d2d65f682c56" 8 | 9 | build() { 10 | # See https://github.com/google/protobuf/issues/2719 11 | case $target in 12 | android-*) export LDFLAGS="$LDFLAGS -llog" ;; 13 | esac 14 | 15 | cd protobuf-$version 16 | autoreconf -i 17 | ./configure --enable-static --disable-shared \ 18 | --host=$cross --prefix=$install_dir --with-protoc=protoc 19 | make 20 | make install 21 | } 22 | 23 | include="include/google/protobuf/*" 24 | lib="lib/libprotobuf-lite.a" 25 | -------------------------------------------------------------------------------- /deps/recipes/zeromq/ios-crash.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/tcp_connecter.cpp b/src/tcp_connecter.cpp 2 | index b8d62a2..dd94a93 100644 3 | --- a/src/tcp_connecter.cpp 4 | +++ b/src/tcp_connecter.cpp 5 | @@ -313,15 +313,10 @@ zmq::fd_t zmq::tcp_connecter_t::connect () 6 | #ifdef ZMQ_HAVE_WINDOWS 7 | zmq_assert (rc == 0); 8 | if (err != 0) { 9 | - if (err != WSAECONNREFUSED 10 | - && err != WSAETIMEDOUT 11 | - && err != WSAECONNABORTED 12 | - && err != WSAEHOSTUNREACH 13 | - && err != WSAENETUNREACH 14 | - && err != WSAENETDOWN 15 | - && err != WSAEACCES 16 | - && err != WSAEINVAL 17 | - && err != WSAEADDRINUSE) 18 | + if (err == WSAEBADF || 19 | + err == WSAENOPROTOOPT || 20 | + err == WSAENOTSOCK || 21 | + err == WSAENOBUFS) 22 | { 23 | wsa_assert_no (err); 24 | } 25 | @@ -335,13 +330,10 @@ 26 | if (err != 0) { 27 | errno = err; 28 | errno_assert ( 29 | - errno == ECONNREFUSED || 30 | - errno == ECONNRESET || 31 | - errno == ETIMEDOUT || 32 | - errno == EHOSTUNREACH || 33 | - errno == ENETUNREACH || 34 | - errno == ENETDOWN || 35 | - errno == EINVAL); 36 | + errno != EBADF && 37 | + errno != ENOPROTOOPT && 38 | + errno != ENOTSOCK && 39 | + errno != ENOBUFS); 40 | return retired_fd; 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /deps/recipes/zeromq/zeromq.recipe: -------------------------------------------------------------------------------- 1 | depends="libsodium" 2 | inherit lib 3 | 4 | version="4.1.5" 5 | source="https://github.com/zeromq/cppzmq.git#ac705f604701e2ca1643fa31bae240f9da8b9b9a 6 | http://download.openpkg.org/components/cache/zmq/zeromq-$version.tar.gz#2b7490b77860be3060b1b1f92cd73184d309ca69" 7 | 8 | build() { 9 | cd zeromq-$version 10 | 11 | echo Patching... 12 | patch -p1 < $recipe_dir/ios-crash.patch 13 | 14 | # The `clock_gettime` function only works on iOS 10, so we can't use it: 15 | case $target in 16 | ios-*) 17 | sed -e s/clock_gettime/clock_gettime_xxx/ configure.ac > configure2.ac 18 | cp configure2.ac configure.ac 19 | ;; 20 | esac 21 | 22 | echo Building... 23 | ./autogen.sh 24 | ./configure --disable-eventfd \ 25 | --enable-static --disable-shared --host=$cross --prefix=$install_dir 26 | make 27 | make install 28 | cp ../zmq.hpp $install_dir/include/zmq.hpp 29 | } 30 | 31 | include="include/zmq.h include/zmq_utils.h include/zmq.hpp" 32 | lib="lib/libzmq.a" 33 | -------------------------------------------------------------------------------- /deps/recipes/zlib/zlib.recipe: -------------------------------------------------------------------------------- 1 | inherit lib 2 | 3 | version="1.2.11" 4 | source="http://zlib.net/zlib-$version.tar.gz#e6d119755acdf9104d7ba236b1242696940ed6dd" 5 | 6 | build() { 7 | cd zlib-$version 8 | CHOST=$cross ./configure --static --prefix=$install_dir 9 | make 10 | make install 11 | } 12 | 13 | include="include/zconf.h include/zlib.h" 14 | lib="lib/libz.a" 15 | -------------------------------------------------------------------------------- /minilibs/catch/readme.md: -------------------------------------------------------------------------------- 1 | # Catch unit-testing library 2 | 3 | This file has been downloaded from 4 | [builds.catch-lib.net](http://builds.catch-lib.net/). 5 | -------------------------------------------------------------------------------- /minilibs/git-sync/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /libgit-sync.a 3 | /sync 4 | /test 5 | -------------------------------------------------------------------------------- /minilibs/git-sync/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -Wall -D_GNU_SOURCE -std=c99 -g -O2 2 | LIBS := $(shell pkg-config --libs libgit2) 3 | 4 | sync: build/main.o build/sync.o 5 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 6 | 7 | libgit-sync.a: build/sync.o 8 | $(AR) rcs libgit-sync.a $^ 9 | 10 | build/test: build/test.o build/sync.o 11 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 12 | 13 | test: build/test 14 | $(RM) -r test 15 | ./build/test 16 | 17 | clean: 18 | $(RM) -r build test 19 | $(RM) sync 20 | $(RM) libgit-sync.a 21 | 22 | # Automatic dependency rules: 23 | build/%.o: %.c 24 | @mkdir -p $(dir $@) 25 | $(CC) -c -MMD $(CFLAGS) -o $@ $< 26 | 27 | include $(shell find build -name *.d) 28 | %.h: ; 29 | -------------------------------------------------------------------------------- /minilibs/git-sync/main.c: -------------------------------------------------------------------------------- 1 | #include "sync.h" 2 | #include 3 | 4 | static void print_error() 5 | { 6 | const git_error *error = giterr_last(); 7 | if (error && error->message) 8 | fprintf(stderr, "libgit2 error: %s\n", error->message); 9 | } 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int rv = 0; 14 | git_repository *repo = NULL; 15 | int files_changed = 0; 16 | int need_push = 0; 17 | 18 | if (git_libgit2_init() < 0) 19 | { 20 | fprintf(stderr, "error: git_threads_init failed\n"); 21 | return 1; 22 | } 23 | 24 | if (argc != 3) 25 | { 26 | fprintf(stderr, "usage: %s \n", argv[0]); 27 | rv = 1; 28 | goto exit; 29 | } 30 | 31 | if (git_repository_open(&repo, argv[1]) < 0) 32 | { 33 | print_error(); 34 | fprintf(stderr, "error: cannot open repository '%s'\n", argv[1]); 35 | rv = 1; 36 | goto exit; 37 | } 38 | 39 | if (sync_fetch(repo, argv[2]) < 0) 40 | { 41 | print_error(); 42 | fprintf(stderr, "error: cannot fetch from '%s'\n", argv[2]); 43 | rv = 1; 44 | goto exit; 45 | } 46 | 47 | if (sync_master(repo, &files_changed, &need_push) < 0) 48 | { 49 | print_error(); 50 | fprintf(stderr, "error: failed to merge\n"); 51 | rv = 1; 52 | goto exit; 53 | } 54 | 55 | if (need_push && sync_push(repo, argv[2]) < 0) 56 | { 57 | print_error(); 58 | fprintf(stderr, "error: cannot push to '%s'\n", argv[2]); 59 | rv = 1; 60 | goto exit; 61 | } 62 | 63 | exit: 64 | if (repo) git_repository_free(repo); 65 | git_libgit2_shutdown(); 66 | return rv; 67 | } 68 | -------------------------------------------------------------------------------- /minilibs/git-sync/readme.md: -------------------------------------------------------------------------------- 1 | # git-sync 2 | 3 | This is a tiny library and command-line utility for syncing files using Git. 4 | The library runs inside the mobile app, 5 | and the command-line utility runs on the server. 6 | -------------------------------------------------------------------------------- /minilibs/git-sync/sync.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Core libgit2-based file-syncing algorithm. 4 | * 5 | * See LICENSE for copy, modification, and use permissions 6 | * 7 | * @author See AUTHORS 8 | * @version 1.0 9 | */ 10 | 11 | #ifndef SYNC_H 12 | #define SYNC_H 13 | 14 | #include 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /** 21 | * Fetches the contents of the server into the "incoming" branch. 22 | */ 23 | int sync_fetch(git_repository *repo, 24 | const char *server); 25 | 26 | /** 27 | * Updates the master branch with the latest changes, including local 28 | * changes and changes from the remote repository. 29 | * @param files_changed set to 1 if the function has changed the workdir. 30 | * @param need_push set to 1 if the master branch has changes not on the 31 | * server. 32 | */ 33 | int sync_master(git_repository *repo, 34 | int *files_changed, 35 | int *need_push); 36 | 37 | /** 38 | * Pushes the master branch to the server. 39 | */ 40 | int sync_push(git_repository *repo, 41 | const char *server); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /minilibs/libbitcoin-client/client.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2014-2015 libbitcoin-client developers (see COPYING). 3 | // 4 | // GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | #ifndef LIBBITCOIN_CLIENT_HPP 8 | #define LIBBITCOIN_CLIENT_HPP 9 | 10 | /** 11 | * API Users: Include only this header. Direct use of other headers is fragile 12 | * and unsupported as header organization is subject to change. 13 | * 14 | * Maintainers: Do not include this header internal to this library. 15 | */ 16 | 17 | #include "message_stream.hpp" 18 | #include "sleeper.hpp" 19 | #include "zeromq_socket.hpp" 20 | #include "obelisk_codec.hpp" 21 | #include "obelisk_router.hpp" 22 | #include "obelisk_types.hpp" 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /minilibs/libbitcoin-client/message_stream.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin-client. 5 | * 6 | * libbitcoin-client is free software: you can redistribute it and/or 7 | * modify it under the terms of the GNU Affero General Public License with 8 | * additional permissions to the one published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) 10 | * any later version. For more information see LICENSE. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef LIBBITCOIN_CLIENT_MESSAGE_STREAM_HPP 21 | #define LIBBITCOIN_CLIENT_MESSAGE_STREAM_HPP 22 | 23 | #include 24 | 25 | namespace libbitcoin { 26 | namespace client { 27 | 28 | /** 29 | * Represents a stream of multi-part messages. 30 | * 31 | * One of this library's design goals is completely separate the networking 32 | * code from the message-handling code. This interface is the glue between 33 | * the two worlds. 34 | */ 35 | class message_stream 36 | { 37 | public: 38 | virtual ~message_stream() {}; 39 | 40 | /** 41 | * Sends one multi-part message. 42 | */ 43 | virtual void write(const data_stack& data) = 0; 44 | }; 45 | 46 | } // namespace client 47 | } // namespace libbitcoin 48 | 49 | #endif 50 | 51 | -------------------------------------------------------------------------------- /minilibs/libbitcoin-client/obelisk_types.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin-client. 5 | * 6 | * libbitcoin-client is free software: you can redistribute it and/or 7 | * modify it under the terms of the GNU Affero General Public License with 8 | * additional permissions to the one published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) 10 | * any later version. For more information see LICENSE. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef LIBBITCOIN_CLIENT_OBELISK_OBELISK_TYPES_HPP 21 | #define LIBBITCOIN_CLIENT_OBELISK_OBELISK_TYPES_HPP 22 | 23 | #include 24 | 25 | namespace libbitcoin { 26 | namespace client { 27 | 28 | struct history_row 29 | { 30 | output_point output; 31 | size_t output_height; 32 | uint64_t value; 33 | input_point spend; 34 | size_t spend_height; 35 | }; 36 | 37 | typedef std::vector history_list; 38 | 39 | struct stealth_row 40 | { 41 | data_chunk ephemkey; 42 | payment_address address; 43 | hash_digest transaction_hash; 44 | }; 45 | 46 | typedef std::vector stealth_list; 47 | 48 | // See below for description of updates data format. 49 | enum class subscribe_type : uint8_t 50 | { 51 | address = 0, 52 | stealth = 1 53 | }; 54 | 55 | } 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /minilibs/libbitcoin-client/sleeper.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin-client. 5 | * 6 | * libbitcoin-client is free software: you can redistribute it and/or 7 | * modify it under the terms of the GNU Affero General Public License with 8 | * additional permissions to the one published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) 10 | * any later version. For more information see LICENSE. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef LIBBITCOIN_CLIENT_SLEEPER_HPP 21 | #define LIBBITCOIN_CLIENT_SLEEPER_HPP 22 | 23 | #include 24 | #include 25 | 26 | namespace libbitcoin { 27 | namespace client { 28 | 29 | /** 30 | * Sentinel value interpreted in sleep timer as infinity. 31 | */ 32 | BC_CONSTEXPR int period_forever = 0; 33 | 34 | /** 35 | * A sleep timer period in milliseconds. 36 | */ 37 | typedef std::chrono::milliseconds period_ms; 38 | 39 | /** 40 | * An interface for objects that need to perform delayed work in a 41 | * non-blocking manner. 42 | * 43 | * Before going to sleep, the program's main loop should call the `wakeup` 44 | * method on any objects that implement this interface. This method will 45 | * return the amount of time until the object wants to be woken up again. 46 | * The main loop should sleep for this long. On the next time around the 47 | * loop, calling the `wakeup` method will perform the pending work 48 | * (assuming enough time has elapsed). 49 | */ 50 | class sleeper 51 | { 52 | public: 53 | virtual ~sleeper() {}; 54 | 55 | /** 56 | * Performs any pending time-based work, and returns the number of 57 | * milliseconds between now and the next time work needs to be done. 58 | * Returns 0 if the class has no future work to do. 59 | */ 60 | virtual period_ms wakeup() = 0; 61 | }; 62 | 63 | /** 64 | * Returns the smaller of two time periods, treating 0 as infinity. 65 | */ 66 | inline period_ms min_sleep(period_ms a, period_ms b) 67 | { 68 | if (a.count() == period_forever) 69 | return b; 70 | if (b.count() == period_forever) 71 | return a; 72 | return std::min(a, b); 73 | } 74 | 75 | } // namespace client 76 | } // namespace libbitcoin 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /minilibs/libbitcoin-client/zeromq_socket.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * libbitcoin is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License with 8 | * additional permissions to the one published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) 10 | * any later version. For more information see LICENSE. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef LIBBITCOIN_CLIENT_SOCKET_HPP 21 | #define LIBBITCOIN_CLIENT_SOCKET_HPP 22 | 23 | #include 24 | #include "message_stream.hpp" 25 | 26 | namespace libbitcoin { 27 | namespace client { 28 | 29 | /** 30 | * Represents a connection to the bitcoin server. 31 | */ 32 | class BC_API zeromq_socket 33 | : public message_stream 34 | { 35 | public: 36 | BC_API ~zeromq_socket(); 37 | BC_API zeromq_socket(void* context, int type=ZMQ_DEALER); 38 | 39 | /** 40 | * Connects to a remote server. 41 | * @param key optional key for encrypted servers. 42 | * @return false if something went wrong. The socket will be unusable 43 | * in that case. 44 | */ 45 | BC_API bool connect(const std::string& address, const std::string& key=""); 46 | 47 | /** 48 | * Begins listening for incoming connections. 49 | * @return false if something went wrong. The socket will be unusable 50 | * in that case. 51 | */ 52 | BC_API bool bind(const std::string& address); 53 | 54 | /** 55 | * Creates a zeromq pollitem_t structure suitable for passing to the 56 | * zmq_poll function. When zmq_poll indicates that there is data waiting 57 | * to be read, simply call the `forward` method to handle it. 58 | */ 59 | BC_API zmq_pollitem_t pollitem(); 60 | 61 | /** 62 | * Forwards pending input messages to the given message_stream interface. 63 | */ 64 | BC_API bool forward(message_stream& dest); 65 | 66 | /** 67 | * Forwards pending input messages to the given zeromq socket in a 68 | * zero-copy manner. 69 | */ 70 | BC_API bool forward(zeromq_socket& dest); 71 | 72 | // message_stream interface: 73 | virtual void write(const data_stack& data); 74 | 75 | private: 76 | /** 77 | * Returns true if there are pending input messages. 78 | */ 79 | bool pending(); 80 | 81 | void* socket_; 82 | }; 83 | 84 | } // namespace client 85 | } // namespace libbitcoin 86 | 87 | #endif 88 | 89 | 90 | -------------------------------------------------------------------------------- /minilibs/scrypt/.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.o 3 | -------------------------------------------------------------------------------- /minilibs/scrypt/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | CFLAGS += -fPIC -O2 3 | 4 | libscrypt.a: crypto_scrypt.o 5 | $(AR) rcs libscrypt.a $^ 6 | 7 | %.o: %.c 8 | $(CC) -c $(CFLAGS) -o $@ $< 9 | 10 | install: libscrypt.a 11 | mkdir -p $(PREFIX)/lib 12 | mkdir -p $(PREFIX)/include/scrypt 13 | cp libscrypt.a $(PREFIX)/lib/ 14 | cp *.h $(PREFIX)/include/scrypt/ 15 | 16 | clean: 17 | $(RM) *.o *.a 18 | -------------------------------------------------------------------------------- /minilibs/scrypt/crypto_scrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef _CRYPTO_SCRYPT_H_ 30 | #define _CRYPTO_SCRYPT_H_ 31 | 32 | #include 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /** 40 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 41 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 42 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 43 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 44 | * must be a power of 2 greater than 1. 45 | * 46 | * Return 0 on success; or -1 on error. 47 | */ 48 | int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 49 | uint32_t, uint32_t, uint8_t *, size_t); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif /* !_CRYPTO_SCRYPT_H_ */ 56 | -------------------------------------------------------------------------------- /minilibs/scrypt/readme.md: -------------------------------------------------------------------------------- 1 | # scrypt 2 | 3 | This source code has been extracted from the 4 | [scrypt command-line utility](https://www.tarsnap.com/scrypt.html) 5 | and turned into a standalone library. 6 | -------------------------------------------------------------------------------- /remove-build-tags.sh: -------------------------------------------------------------------------------- 1 | for tag in $(git tag | egrep "[0-9]+.[0-9]+.[0-9]+.*"); do 2 | git tag -d $tag 3 | done 4 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | Test 2 | xcuserdata 3 | Version.h 4 | -------------------------------------------------------------------------------- /src/HandleCache.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef SRC_HANDLE_CACHE_HPP 9 | #define SRC_HANDLE_CACHE_HPP 10 | 11 | #include "../abcd/util/Status.hpp" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace abcd { 17 | 18 | /** 19 | * Provides a mapping between opaque integer handles and internal C++ objects. 20 | */ 21 | template 22 | class HandleCache 23 | { 24 | public: 25 | /** 26 | * Looks up a handle, returning the referenced object. 27 | */ 28 | Status 29 | find(std::shared_ptr &result, int handle) const 30 | { 31 | std::lock_guard lock(mutex_); 32 | 33 | auto i = cache_.find(handle); 34 | if (cache_.end() == i) 35 | return ABC_ERROR(ABC_CC_NULLPtr, "Invalid handle"); 36 | 37 | result = i->second; 38 | return Status(); 39 | } 40 | 41 | /** 42 | * Inserts a pointer into the cache, returning a new handle. 43 | */ 44 | int 45 | insert(std::shared_ptr p) 46 | { 47 | std::lock_guard lock(mutex_); 48 | 49 | auto handle = ++lastHandle_; 50 | cache_[handle] = p; 51 | return handle; 52 | } 53 | 54 | /** 55 | * Removes an item from the cache. 56 | */ 57 | void 58 | erase(int handle) 59 | { 60 | std::lock_guard lock(mutex_); 61 | 62 | cache_.erase(handle); 63 | } 64 | 65 | private: 66 | mutable std::mutex mutex_; 67 | int lastHandle_ = 0; 68 | std::unordered_map> cache_; 69 | }; 70 | 71 | } // namespace abcd 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/TxDetails.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "TxDetails.hpp" 9 | #include "../abcd/util/Util.hpp" 10 | 11 | namespace abcd { 12 | 13 | void 14 | ABC_TxDetailsFree(tABC_TxDetails *pDetails) 15 | { 16 | if (pDetails) 17 | { 18 | ABC_FREE_STR(pDetails->szName); 19 | ABC_FREE_STR(pDetails->szCategory); 20 | ABC_FREE_STR(pDetails->szNotes); 21 | ABC_CLEAR_FREE(pDetails, sizeof(tABC_TxDetails)); 22 | } 23 | } 24 | 25 | } // namespace abcd 26 | -------------------------------------------------------------------------------- /src/TxDetails.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | /** 8 | * @file 9 | * Helpers for dealing with Airbitz transaction metadata. 10 | */ 11 | 12 | #ifndef SRC_TX_DETAILS_HPP 13 | #define SRC_TX_DETAILS_HPP 14 | 15 | #include "../abcd/util/Status.hpp" 16 | 17 | namespace abcd { 18 | 19 | /** 20 | * Free a TX details struct 21 | */ 22 | void 23 | ABC_TxDetailsFree(tABC_TxDetails *pDetails); 24 | 25 | } // namespace abcd 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/TxInfo.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #ifndef SRC_TX_INFO_HPP 9 | #define SRC_TX_INFO_HPP 10 | 11 | #include "../abcd/util/Status.hpp" 12 | 13 | namespace abcd { 14 | 15 | struct TxInfo; 16 | struct TxStatus; 17 | class Wallet; 18 | 19 | /** 20 | * Converts the modern `TxInfo` structure to the API's `tABC_TxInfo` structure, 21 | * using information from the wallet's metadatabase. 22 | */ 23 | tABC_TxInfo * 24 | makeTxInfo(Wallet &self, const TxInfo &info, const TxStatus &status); 25 | 26 | tABC_CC ABC_TxGetTransactions(Wallet &self, 27 | int64_t startTime, 28 | int64_t endTime, 29 | tABC_TxInfo ***paTransactions, 30 | unsigned int *pCount, 31 | tABC_Error *pError); 32 | 33 | tABC_CC ABC_TxSearchTransactions(Wallet &self, 34 | const char *szQuery, 35 | tABC_TxInfo ***paTransactions, 36 | unsigned int *pCount, 37 | tABC_Error *pError); 38 | 39 | void ABC_TxFreeTransaction(tABC_TxInfo *pTransactions); 40 | 41 | void ABC_TxFreeTransactions(tABC_TxInfo **aTransactions, 42 | unsigned int count); 43 | 44 | } // namespace abcd 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/Version.h.in: -------------------------------------------------------------------------------- 1 | #ifndef VERSION_h 2 | #define VERSION_h 3 | 4 | #define ABC_VERSION "1c3acc7" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/Bitcoin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../abcd/bitcoin/Utility.hpp" 9 | #include "../abcd/crypto/Encoding.hpp" 10 | #include "../abcd/json/JsonBox.hpp" 11 | #include "../minilibs/catch/catch.hpp" 12 | 13 | #include 14 | 15 | static const char rawTxHex[] = 16 | "0100000000010170632233be35f8b6deb07e0e13d31cd6efa03b5a7e05afe619e5017acda23b6400000000171600145888c0ee06ce9ceaebe253d67e7e547f8bb3db05ffffffff0132430300000000001976a9143801b8cff780ca0853df97d247ab64980cc0638e88ac0247304402203470c6871ae67ae74d6eced94d57f4970e10a52523d329991fa21caa7125876d0220628ae0c349333d7636e6a14ce1e1defd2459b3b5d44b1a4fe96593e00da321c40121033f0463711a8815af06cbfc44d73ce8f5da613e81ddd83413a4af08d5b3ff2f8000000000"; 17 | 18 | TEST_CASE("Decode segwit transaction", "[bitcoin]") 19 | { 20 | abcd::DataChunk rawTx; 21 | abcd::base16Decode(rawTx, rawTxHex); 22 | 23 | bc::transaction_type result; 24 | CHECK(abcd::decodeTx(result, rawTx)); 25 | REQUIRE(result.inputs.size() == 1); 26 | REQUIRE(result.outputs.size() == 1); 27 | REQUIRE(result.locktime == 0); 28 | } 29 | -------------------------------------------------------------------------------- /test/Bitid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../abcd/login/Bitid.hpp" 9 | #include "../abcd/http/Uri.hpp" 10 | #include "../minilibs/catch/catch.hpp" 11 | 12 | TEST_CASE("BitID callback tests", "[login][bitid]") 13 | { 14 | const std::string path = "bitid.bitcoin.blue/callback"; 15 | abcd::Uri result; 16 | 17 | SECTION("no authority") 18 | { 19 | REQUIRE(abcd::bitidCallback(result, "bitid:" + path + "?x=1")); 20 | REQUIRE(result.encode() == "https://" + path); 21 | } 22 | SECTION("normal") 23 | { 24 | REQUIRE(abcd::bitidCallback(result, "bitid://" + path + "?x=1")); 25 | REQUIRE(result.encode() == "https://" + path); 26 | } 27 | SECTION("no https") 28 | { 29 | REQUIRE(abcd::bitidCallback(result, "bitid://" + path + "?x=1&u=1")); 30 | REQUIRE(result.encode() == "http://" + path); 31 | } 32 | } 33 | 34 | TEST_CASE("BitID key derivation", "[login][bitid]") 35 | { 36 | bc::word_list mnemonic = 37 | { 38 | "inhale", "praise", "target", "steak", "garlic", "cricket", 39 | "paper", "better", "evil", "almost", "sadness", "crawl", 40 | "city", "banner", "amused", "fringe", "fox", "insect", 41 | "roast", "aunt", "prefer", "hollow", "basic", "ladder" 42 | }; 43 | const auto signature = abcd::bitidSign(bc::decode_mnemonic(mnemonic), 44 | "test", "http://bitid.bitcoin.blue/callback", 0); 45 | REQUIRE(signature.address == "1J34vj4wowwPYafbeibZGht3zy3qERoUM1"); 46 | } 47 | -------------------------------------------------------------------------------- /test/Crypto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../abcd/crypto/Crypto.hpp" 9 | #include "../abcd/crypto/Encoding.hpp" 10 | #include "../abcd/json/JsonBox.hpp" 11 | #include "../minilibs/catch/catch.hpp" 12 | 13 | // sha256("Satoshi"): 14 | static const char keyHex[] = 15 | "002688cc350a5333a87fa622eacec626c3d1c0ebf9f3793de3885fa254d7e393"; 16 | 17 | TEST_CASE("File name", "[crypto]") 18 | { 19 | const std::string name("1PeChFbhxDD9NLbU21DfD55aQBC4ZTR3tE"); 20 | const std::string key("Satoshi"); 21 | CHECK(abcd::cryptoFilename(key, name) == 22 | "5vJNMWZ68tsp2HJa1AfMhZpcpU9Wm9ccEw7cTwvARHXh"); 23 | } 24 | 25 | TEST_CASE("Decryption", "[crypto][encryption]") 26 | { 27 | tABC_Error error; 28 | abcd::DataChunk key; 29 | abcd::base16Decode(key, keyHex); 30 | abcd::JsonBox box; 31 | box.decode( 32 | "{" 33 | "\"data_base64\": " 34 | "\"X08Snnou2PrMW21ZNyJo5C8StDjTNgMtuEoAJL5bJ6LDPdZGQLhjaUMetOknaPYn" 35 | "mfBCHNQ3ApqmE922Hkp30vdxzXBloopfPLJKdYwQxURYNbiL4TvNakP7i0bnTlIsR7" 36 | "bj1q/65ZyJOW1HyOKV/tmXCf56Fhe3Hcmb/ebsBF72FZr3jX5pkSBO+angK15IlCIi" 37 | "em1kPi6QmzyFtMB11i0GTjSS67tLrWkGIqAmik+bGqy7WtQgfMRxQNNOxePPSHHp09" 38 | "431Ogrc9egY3txnBN2FKnfEM/0Wa/zLWKCVQXCGhmrTx1tmf4HouNDOnnCgkRWJYs8" 39 | "FJdrDP8NZy4Fkzs7FoH7RIaUiOvosNKMil1CBknKremP6ohK7SMLGoOHpv+bCgTXcA" 40 | "eB3P4Slx3iy+RywTSLb3yh+HDo6bwt+vhujP0RkUamI5523bwz3/7vLO8BzyF6WX0B" 41 | "y2s4gvMdFQ==\"," 42 | "\"encryptionType\": 0," 43 | "\"iv_hex\": \"96a4cd52670c13df9712fdc1b564d44b\"" 44 | "}"); 45 | 46 | abcd::DataChunk data; 47 | CHECK(box.decrypt(data, key)); 48 | CHECK(abcd::toString(data) == "payload"); 49 | } 50 | 51 | TEST_CASE("Encryption round-trip", "[crypto][encryption]") 52 | { 53 | tABC_Error error; 54 | abcd::DataChunk key; 55 | abcd::base16Decode(key, keyHex); 56 | const std::string payload("payload"); 57 | 58 | abcd::JsonBox box; 59 | CHECK(box.encrypt(payload, key)); 60 | 61 | abcd::DataChunk data; 62 | CHECK(box.decrypt(data, key)); 63 | CHECK(abcd::toString(data) == payload); 64 | } 65 | -------------------------------------------------------------------------------- /test/Main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | // Allow Catch to to generate our main function: 9 | #define CATCH_CONFIG_MAIN 10 | #include "../minilibs/catch/catch.hpp" 11 | -------------------------------------------------------------------------------- /test/OtpKey.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../abcd/crypto/OtpKey.hpp" 9 | #include "../abcd/crypto/Encoding.hpp" 10 | #include "../minilibs/catch/catch.hpp" 11 | 12 | TEST_CASE("RFC 4226 test vectors", "[crypto][otp]" ) 13 | { 14 | std::string secretData = "12345678901234567890"; 15 | abcd::OtpKey key(secretData); 16 | 17 | const char *cases[] = 18 | { 19 | "755224", 20 | "287082", 21 | "359152", 22 | "969429", 23 | "338314", 24 | "254676", 25 | "287922", 26 | "162583", 27 | "399871", 28 | "520489" 29 | }; 30 | int i = 0; 31 | for (auto test: cases) 32 | { 33 | REQUIRE(key.hotp(i) == test); 34 | ++i; 35 | } 36 | } 37 | 38 | TEST_CASE("Leading zeros in OTP output", "[crypto][otp]" ) 39 | { 40 | abcd::OtpKey key; 41 | REQUIRE(key.decodeBase32("AAAAAAAA")); 42 | REQUIRE(key.hotp(2) == "073348"); 43 | REQUIRE(key.hotp(9) == "003773"); 44 | } 45 | -------------------------------------------------------------------------------- /test/Scrypt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Airbitz, Inc. 3 | * All rights reserved. 4 | * 5 | * See the LICENSE file for more information. 6 | */ 7 | 8 | #include "../abcd/crypto/Scrypt.hpp" 9 | #include "../abcd/crypto/Encoding.hpp" 10 | #include "../minilibs/catch/catch.hpp" 11 | 12 | TEST_CASE("Scrypt RFC test vectors", "[crypto][scrypt]") 13 | { 14 | struct TestCase 15 | { 16 | std::string password; 17 | std::string salt; 18 | uint64_t N; 19 | uint32_t r; 20 | uint32_t p; 21 | size_t dklen; 22 | const char *result; 23 | }; 24 | TestCase cases[] = 25 | { 26 | { 27 | "", "", 16, 1, 1, 64, 28 | "77d6576238657b203b19ca42c18a0497" 29 | "f16b4844e3074ae8dfdffa3fede21442" 30 | "fcd0069ded0948f8326a753a0fc81f17" 31 | "e8d3e0fb2e0d3628cf35e20c38d18906" 32 | }, 33 | #if SLOW_SCRYPT_TESTS 34 | { 35 | "password", "NaCl", 1024, 8, 16, 64, 36 | "fdbabe1c9d3472007856e7190d01e9fe" 37 | "7c6ad7cbc8237830e77376634b373162" 38 | "2eaf30d92e22a3886ff109279d9830da" 39 | "c727afb94a83ee6d8360cbdfa2cc0640" 40 | }, 41 | { 42 | "pleaseletmein", "SodiumChloride", 16384, 8, 1, 64, 43 | "7023bdcb3afd7348461c06cd81fd38eb" 44 | "fda8fbba904f8e3ea9b543f6545da1f2" 45 | "d5432955613f0fcf62d49705242a9af9" 46 | "e61e85dc0d651e40dfcf017b45575887" 47 | }, 48 | { 49 | "pleaseletmein", "SodiumChloride", 1048576, 8, 1, 64, 50 | "2101cb9b6a511aaeaddbbe09cf70f881" 51 | "ec568d574a2ffd4dabe5ee9820adaa47" 52 | "8e56fd8f4ba5d09ffa1c6d927c40f4c3" 53 | "37304049e8a952fbcbf45c6fa77a41a4" 54 | } 55 | #else 56 | { 57 | "air", "bitz", 16, 2, 1, 64, // Fast, but not from the RFC 58 | "a7baec15cc38090b1ec207421105acbd" 59 | "ad4e046be2ac04c3ecf5c01710691496" 60 | "92040affcee0b7bd0798dd284ae26268" 61 | "b17933839588c9bf1bd2d62baddf3fbb" 62 | } 63 | #endif 64 | }; 65 | 66 | for (auto &test: cases) 67 | { 68 | abcd::ScryptSnrp snrp = 69 | { 70 | abcd::DataChunk(test.salt.begin(), test.salt.end()), 71 | test.N, test.r, test.p 72 | }; 73 | abcd::DataChunk out; 74 | unsigned long totalTime; 75 | CHECK(snrp.hash(out, test.password, &totalTime, test.dklen)); 76 | CHECK(abcd::base16Encode(out) == test.result); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /util/.gitignore: -------------------------------------------------------------------------------- 1 | bitcoin.sh 2 | -------------------------------------------------------------------------------- /util/airbitz-keygen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ $# -ne 2 ]; then 3 | echo "usage: " 4 | exit 1 5 | fi 6 | 7 | private=$(bx hd-new $1 | bx hd-private -i 0 | bx hd-private -i 0 | bx hd-private -i $2) 8 | bx hd-to-wif $private 9 | bx hd-to-address $private 10 | 11 | # Only generate a testnet address if the necessary bitcoin-bash-tools 12 | # are available (https://github.com/grondilu/bitcoin-bash-tools): 13 | if [ -f bitcoin.sh ]; then 14 | . bitcoin.sh 15 | decoded=$(decodeBase58 $(bx hd-to-address $private)) 16 | hexToAddress ${decoded:2:40} 6F 17 | fi 18 | -------------------------------------------------------------------------------- /util/airbitz-pubkeygen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | if [ $# -ne 2 ]; then 4 | echo "usage: " 5 | exit 1 6 | fi 7 | 8 | public=$(bx hd-public -i 0 $1) 9 | 10 | for index in $(seq 0 $2) 11 | do 12 | address=$(bx hd-public -i $index $public | bx hd-to-address) 13 | echo $address '#'$index 14 | done 15 | -------------------------------------------------------------------------------- /util/git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | hasFormattingIssues=0 4 | 5 | if ! command -v astyle >/dev/null ; then 6 | echo "error: please install astyle in order to be able" \ 7 | " to use this pre-commit git-hook" 8 | exit 1 9 | fi 10 | 11 | if git rev-parse --verify HEAD >/dev/null 2>&1; then 12 | against=HEAD 13 | else 14 | # Initial commit: diff against an empty tree object 15 | against=2caab4551b305ab1e9e4b05145a4da5f51331e0d 16 | fi 17 | 18 | # Redirect output to stderr. 19 | exec 1>&2 20 | 21 | files=$(git diff --cached --name-only --diff-filter=AM $against | \ 22 | grep -E '^(abcd|cli|src|tests|util)' | grep -E '\.(c|h|cpp|hpp)$') 23 | 24 | for file in $files; do 25 | astyle --options=astyle-options -Q $file 26 | if [ -e "$file.orig" ]; then 27 | mv $file "$file.formated" 28 | mv "$file.orig" $file 29 | git diff --no-index "$file" "$file.formated" | cat 30 | 31 | isDiff=$(diff --brief "$file.formated" $file) 32 | if [ "$isDiff" != "" ] ; then 33 | hasFormattingIssues=1 34 | fi 35 | rm "$file.formated" 36 | fi 37 | done 38 | 39 | if [ $hasFormattingIssues -eq 1 ] ; then 40 | echo Found code style formatting issues. 41 | exit 1 42 | fi 43 | --------------------------------------------------------------------------------