GithubHelp home page GithubHelp logo

keeshux / bitcoinspv Goto Github PK

View Code? Open in Web Editor NEW
88.0 5.0 14.0 1.64 MB

A native Bitcoin SPV client library for iOS with BIP32 support.

License: GNU General Public License v3.0

Objective-C 99.76% Ruby 0.24%
bitcoin blockchain objective-c wallet hd-wallet transaction

bitcoinspv's Introduction

BitcoinSPV

BitcoinSPV is a native Bitcoin SPV (Simplified Payment Verification) client library for iOS written in Objective-C. It conveniently supports Bloom filters (BIP37) and hierarchical deterministic wallets (BIP32).

BitcoinSPV is still experimental and you DO NOT want to use it in production environments today.

Structure

The library is thorough and features a moderately high granularity to isolate the smallest bits of the Bitcoin protocol. Many atomic classes make up the whole thing in tiny steps while also decoupling the user from the areas he's not interested in, because files interdependency is kept at an unnoticeable minimum.

Grouped by area:

  • Global

    • Constant values of the Bitcoin ecosystem.
    • Specific library settings unrelated to Bitcoin.
    • Domain and codes found in the NSError objects returned by the library.
    • Useful macros for frequent operations.
  • Parameters

    • Here you find network-specific magic numbers and parameters.
  • Core

    • Generic binary data (de)serialization (WSBuffer).
    • Hashes used everywhere for transaction and block ids, addresses, checksums etc. (WSHash256, WSHash160).
    • ECDSA keys wrappers, able to also import WIF private keys (WSKey, WSPublicKey).
    • Scripts as the key part of the Bitcoin transaction system (WSScript).
    • Transaction family classes will help you decode binary transactions or build/sign your own from inputs, outputs and keys (WSTransaction).
    • Addresses are just a shorter way to visualize a transaction script, all standard forms (P2PK, P2PKH, P2SH) are supported (WSAddress).
    • An extensive implementation of a BIP32 HD keyring (WSHDKeyring).
  • Blockchain

  • Protocol

    • Almost all protocol messages are defined here, one class per message.
    • Bloom filters as defined by BIP37 (WSBloomFilter).
  • Networking

    • Enter the P2P Bitcoin network (WSPeerGroup).
    • Download the blockchain from the network (WSBlockChainDownloader).
    • Connection pooling when dealing with multiple peers (WSConnectionPool).
    • Blockchain SPV synchronization with Bloom filtering for low bandwidth usage.
  • Wallet

    • Generic wallet representations.
    • A fully BIP32-compliant HD wallet (WSHDWallet).
  • Currency

  • Web

    • Useful operations accomplished with the aid of third-party web services.
    • Explorer classes from different providers (WSWebExplorer).
    • Ticker classes and unified price monitor (WSWebTicker, WSWebTickerMonitor).
    • Sweep an external private key (e.g. a paper wallet), be it plain or password-encrypted (BIP38).
  • BIPS

    • BIP21: parsing and building of "bitcoin:" URLs.
    • BIP32: hierarchical deterministic wallets.
    • BIP37: Bloom filtering for fast blockchain synchronization.
    • BIP38: passphrase-protected private keys.
    • BIP39: mnemonics for deterministic keys.
    • BIP44: multi-account hierarchy for deterministic wallets.

Installation

BitcoinSPV depends on four well known libraries:

Setup is straightforward thanks to the brilliant CocoaPods utility. I usually test the software on iOS 7 but everything should be fine on 6.x as well.

Podfile

Add the following line:

pod 'BitcoinSPV', '~> 0.7.1'

and run on the terminal:

$ pod install

Beware that some recent versions of CocoaPods may break static linking unless you remove the following line from the Pods/Pods.*.xcconfig configuration files:

OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)

Imports

All the imports are public but the one you generally need is #import "BitcoinSPV.h".

Testing

The BitcoinSPVTests target comes with a couple of automated tests. They don't completely test all the library features (especially the networking area), but they're certainly required to succeed. A single fail guarantees that something's broken.

Some tests write files on disk in the global Library/Caches of the iPhone Simulator. You can find them under the BitcoinSPVTests subdirectory.

Basic usage

Developers familiar with bitcoinj may recall some of the class names in the following snippets:

Create new wallet

#import "BitcoinSPV.h"

- (void)createWallet
{
    WSParameters *parameters = WSParametersForNetworkType(WSNetworkTypeTestnet3);

    WSSeed *seed = [[WSSeedGenerator sharedInstance] generateRandomSeed];

    // now's the time to backup the seed somewhere, show it to the user etc.

    id<WSBlockStore> store = [[WSMemoryBlockStore alloc] initWithParameters:parameters];
    WSHDWallet *wallet = [[WSHDWallet alloc] initWithParameters:parameters seed:seed];
    WSBlockChainDownloader *downloader = [[WSBlockChainDownloader alloc] initWithStore:store wallet:wallet];
    
    WSPeerGroup *peerGroup = [[WSPeerGroup alloc] initWithParameters:parameters];
    [peerGroup startConnections];
    [peerGroup startDownloadWithDownloader:downloader];

    // strongly retain peer group
    self.peerGroup = peerGroup;
}

Restore existing wallet

#import "BitcoinSPV.h"

- (void)restoreWallet
{
    WSParameters *parameters = WSParametersForNetworkType(WSNetworkTypeTestnet3);

    WSSeed *seed = WSSeedMakeFromISODate(@"enter your bip39 mnemonic seed phrase", @"2014-02-28");

    id<WSBlockStore> store = [[WSMemoryBlockStore alloc] initWithParameters:parameters];
    WSHDWallet *wallet = [[WSHDWallet alloc] initWithParameters:parameters seed:seed];
    WSBlockChainDownloader *downloader = [[WSBlockChainDownloader alloc] initWithStore:store wallet:wallet];
    
    WSPeerGroup *peerGroup = [[WSPeerGroup alloc] initWithParameters:parameters];
    [peerGroup startConnections];
    [peerGroup startDownloadWithDownloader:downloader];

    // strongly retain peer group
    self.peerGroup = peerGroup;
}

Overview

Network parameters

Bitcoin nodes can operate on three networks:

  • Main: that's the real world network where coins have real value.
  • Testnet3: test coins are quite hard to mine but have negligible value. Online faucets exist to earn test coins.
  • Regtest: mining time is trivial on regtest so it's best suited for testing manually built blockchains.

Most initializers depend on network parameters, you can get a reference with the following code:

// networkType must be one of: WSNetworkTypeMain, WSNetworkTypeTestnet3, WSNetworkTypeRegtest

WSParameters *networkParameters = WSParametersForNetworkType(WSNetworkTypeTestnet3);
...

WARNING: operating on main network may cost you real money, make sure you know what you're doing!

Mnemonics

BIP39 gives special hints on how human-readable phrases (mnemonics) can produce a binary seed for HD wallets. BitcoinSPV implements the BIP39 specification in the WSSeedGenerator class that can be used to:

  • Generate a random mnemonic.
  • Convert a mnemonic to binary data.
  • Convert binary data to a mnemonic.
  • Derive key data from a mnemonic.

However, mnemonics in BitcoinSPV are usually wrapped in a WSSeed object that also contains the time the mnemonic was first created. Blockchain sync time can be dramatically faster by specifying such a time (called the "fast catch-up time") because blocks found before won't contain relevant transactions to our wallet and can be safely skipped.

Hierarchical deterministic wallets

HD wallets are described in BIP32. In BitcoinSPV they're instances of the WSHDWallet class and built from a WSSeed object with an optional gap limit (default is 10). An additional set of look-ahead addresses is also pregenerated internally to prevent Bloom filter from being reloaded each time a transaction consumes a new address.

It's worth noting that the seed mnemonic is a very sensitive information -it technically holds all your coins- and as such it's not serialized with the [WSWallet saveToPath:] method: this means you must store it elsewhere, e.g. in the keychain. The mnemonic will be vital to restore later a serialized wallet with the [WSHDWallet loadFromPath:parameters:seed:] method.

Block store

Classes implementing the WSBlockStore protocol take charge of serializing a blockchain. There is currently one implementation: WSMemoryBlockStore. The name is quite self-explanatory.

Peer group

The WSPeerGroup class holds the whole logic for connecting to the Bitcoin network and is the main event notification source. A group can simultaneously connect to several nodes, enforce the number of connected nodes and download the blockchain to a block store. When built with a wallet it also forwards relevant blocks and transactions to the wallet. The wallet in turn registers them and internally updates its history, UTXOs, confirmations etc.

Last but not least, the key interaction with the network is clearly the ability of publishing transactions. Not surprisingly, this is done with the publishTransaction: method.

Insights

Endianness

Bitcoin structures are generally little-endian, an example consequence is that transaction and block hashes are seen "reversed" in hex editors compared to how we see them on web blockchain explorers like Blockchain.info. There are exceptions, though, because network addresses retain the standard big-endian byte order. Yes, this all makes binary encoding quite error-prone.

That's why BitcoinSPV wraps the encoding internals in the WSBuffer and WSMutableBuffer classes. With a buffer class you can safely read/write arbitrary bytes or basic structures like hashes, network addresses, inventories etc. without the hassle of protocol byte order.

Immutability

BitcoinSPV relies on the Grand Central Dispatch, meaning that most of the code is expected to run on multiple queues to achieve best performance. In an attempt to limit the overall complexity, I cut mutable objects usage to a minimum. The immutable approach dramatically simplifies critical sections and guarantees the integrity of serialized data for free. No Core Data entity is mutable, nor are blockchain-related structures in general. Think about it, altering an accepted block would even defeat the purpose of the protocol.

Security

Sensitive data are never serialized automatically so that clients will be able to save them by other, safer means. For example, transactions and addresses of a HD wallet can be safely written to a file, while the secret mnemonic deserves more attention. You may store it encrypted into the keychain, you may retrieve it encrypted from a service provider and decrypt it locally, you may even decide not to store it at all. In fact there's total freedom on how to preserve mnemonics security.

Known issues

BitcoinSPV is still a work-in-progress and will eventually undergo huge modifications. Several basic things are left to do, sorted by priority:

  • Build multi-signature transactions (support is incomplete).
  • Implement payment protocol as described by BIP70/BIP71/BIP72/BIP73.
  • Improve SPV security by tracking peer confidence.
  • Support basic wallets with static keys.
  • Cope with Core Data versioning.

License

BitcoinSPV is released under the GPLv3.

Basically those willing to use BitcoinSPV for their software are forced to release their source as well, because the whole point is about keeping Bitcoin-related software as transparent as possible to increase both trust and community contributions.

Nothing more is due as long as this rule of thumb is followed, still a note in the credits would be appreciated.

Credits

  • bitcoinj - The most popular Bitcoin library for Java.
  • breadwallet - An open source Bitcoin wallet for iOS.
  • bip32.org - Deterministic wallets for JavaScript.

Disclaimer

The developer takes no responsibility for lost money or any damage due to BitcoinSPV regular usage or bugs. Use at your own risk.

Contacts

Twitter: @keeshux

Website: davidederosa.com

bitcoinspv's People

Contributors

keeshux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

bitcoinspv's Issues

[TESTNET] Pending transaction is rejected: Non-canonical signature: S value is unnecessarily high

Am creating and signing new transaction just fine like this:

NSError *error;
WSAddress *address = WSAddressFromString(self.parameters, @"mu4CVtiGvVtE2wHosbHC58RE2hG4CnHnvj");
const uint64_t value = 5213;

WSTransactionBuilder *builder = [self.wallet buildTransactionToAddress:address forValue:value fee:0 error:&error];

WSSignedTransaction *tx = [self.wallet signedTransactionWithBuilder:builder error:&error];

DDLogInfo(@"Tx: %@", tx);

if (![self.peerGroup publishTransaction:tx]) {
    DDLogInfo(@"Publish failed, no connected peers");
    return;
}

Here is the signed tx info:

version = 1,
id = 880afa2349cc47ed3c510c433b744e2f8810327a82e7a3a83a71b4fb577742dc,
size = 227 bytes,
coinbase = NO,
lockTime = 0,
inputs =
{(
{address='mrnE6Yxhk2fgpv4XfGygFU1vRizse3eEju', outpoint=7ec02457c4a6079f852ba029552efbf0be527f5abc22355934b5d35917ede6a3:0, script='[304602210080aace26ee3cce97f219430d60c7638f66383384e3554525647d3adf4f8ceda9022100b47327cad11dda8a5db891535abcddf36dde7766338d1bf00190db9168dee1a101] [0342468eba0e276ae2d1242095690735846a216f0e6b037a9268779d854f622a00]', sequence=0xffffffff}
)},
outputs =
{(
{address='mu4CVtiGvVtE2wHosbHC58RE2hG4CnHnvj', value=5213, script='DUP HASH160 [94826312542abcdd7cf86494a55dc4ed1bd9aad0] EQUALVERIFY CHECKSIG'},
{address='moNtTSY3abxJQFyyKGDMZvBswifVg7dTJy', value=12345510, script='DUP HASH160 [563a7982692821c0d5f43b8c60410554703d8090] EQUALVERIFY CHECKSIG'}
)}

After being published I've got reject message from all the peers:

Received reject from (83.227.31.14:18333): <WSMessageReject: 0x60000046bc40> {message='tx', code=40, reason='non-mandatory-script-verify-flag (Non-canonical signature: S value is unnecessarily high)'}

Googling the issue doesn't help much. Am I missing something? @keeshux

Thanks

collapse

Use dome, click downloads, and make mistakes
wx20180625-190405

The file DDTTYLogger.h can't be found

When i git clone the project to my desk, and pod install again, got an error that the file of DDTTYLogger.h can,t find always.

What is the reason?

Use in production environments

Hello keeshux!

I saw you recommend not to use your work since it’s still experimental.
At which point can we consider your code to be « unsafe » ?
I’d like to integrate it to general public apps but would like to know your opinion first, since it may handle real money, I need to make sure it is (at a minimum) reliable.

Bye for now!
Thanks.

Need help in configuring SPV client for OracolXor blockchain

Currently we're working on integrating bitcoinspv for OracolXOR wallet and we're facing issue in network connection to get balance, unspent txn, and all other server calls. Can someone please help us. Below is the WSParametersBuilder config class.

    builder.magicNumber                 = 0xd9b4bef9;
    builder.publicKeyAddressVersion     = 0x89;
    builder.scriptAddressVersion        = 0x05;
    builder.privateKeyVersion           = 0x80;
    builder.peerPort                    = 5001;
    builder.bip32PublicKeyVersion       = 0x0488b21e; // "xpub"
    builder.bip32PrivateKeyVersion      = 0x0488ade4; // "xprv"
    builder.maxProofOfWork              = 0x1d00ffff;
    builder.retargetTimespan            = 2 * WSDatesOneWeek;   // the targeted timespan between difficulty target adjustments
    builder.minRetargetTimespan         = builder.retargetTimespan / 4;
    builder.maxRetargetTimespan         = builder.retargetTimespan * 4;
    builder.retargetSpacing             = 10 * WSDatesOneMinute;
    builder.retargetInterval            = builder.retargetTimespan / builder.retargetSpacing; // 2016
    
    builder.genesisVersion              = 1;
    builder.genesisMerkleRoot           = WSHash256FromHex(@"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
    builder.genesisTimestamp            = 1231006505;
    builder.genesisBits                 = 0x1d00ffff;
    builder.genesisNonce                = 2083236893;

    builder.dnsSeeds = @[@"192.227.107.209"];
    
    builder.checkpointsHex = @"010000002f82b87670845faadde3fedd0dbf5040db62ba2b25c23e2c8408c17400000000ed73df5023c8e8f477fb965fe4c3cbfe5ee34b7d8b56c3efa3f3f9c0b275c91318526a4affff001dd953970400c04e0000064ec14ec14ec1010000001a231097b6ab6279c80f24674a2c8ee5b9a848e1d45715ad89b6358100000000a822bafe6ed8600e3ffce6d61d10df1927eafe9bbf677cb44c4d209f143c6ba8db8c784b5746651cce22211800809d000006aa83470b022201000000934c2bd5a456180b404341a380d20f51d0862b38311deb4d9505450900000000299a1702e49cf69bc3d0a6eee27510cc3cca5a427e1d000b2ccaf907116aaf4822c6124c64ba0e1c5423c2040040ec000007033108918048f5010000000e860de65c35a94d2e335be7d79aabb6e3ddf3918e6d65c61e5b230000000000e36abc2127229d3a94ae0e2067a0a75cab61629d5b2f01b927df43b6c0025a08976f954ced66471bfb11bb0300003b010007573c8422533f6201000000ddf75090bebe04fd00bd5d54945a7e775ff21a012374e284fe5a0200000000007a71100da32b454f15e1863b6dda148c830f92c0e99806c10f69ac6392ea3cb9335a214dcb04041b24da04f800c08901000806f5a2514ecc5ae0010000003d03ef67e92310f1f1161fcf6e3631bcd25a93e5e422b5ac84a30000000000007096173096e73db173c4b21ae76bbbbf655ebb5bd9662e91da721144c54eeada8c79bb4dfa98001b5898b8540080d8010008426823e1d78011b6010000000a5d88ccd0c56b9bbe4c84acae7250a2d4dc5ba92f52783dd3070000000000002c92030e6281be57bec776b084dc316febfcb2487ab96ec71708af36531955e976af494e864a091a1dda09ed004027020009047170e1c12bfa4b3001000000c48381c43b1d2ebd386c70971289aa69e974ff281fedd27f1b03000000000000fcec0145025b8ac811b486fc91f07f5a39a2170c2eee1066238dda4545af70b6c8df094fd7690d1a350999b50000760200090b2788722844ce4bff01000000b807c2dec8b735f71bba13196f69dc26d2c75ea831862bd7b4040000000000009061c7196a009b9616b0cbc1a93e70c6334e1bd6efe27908850ab034c659fef29579be4f5f8b0a1a225d77a700c0c40200091214b3a76adad52bb6010000009d6f4e09d579c93015a83e9081fee83a5c8b1ba3c86516b61f0400000000000025399317bb5c7c4daefe8fe2c4dfac0cea7e4e85913cd667030377240cadfe93a4906b50087e051a84297df70080130300091bd19c9ad8596dd8d001000000747ccc507cb0be8b458daaaf94c168f48a555fda0995a84cb3030000000000001460f2f1855d75fc1be8aaf21b58b004fecaae04ffc681b9c6cfda641f6221d7367a21515c98041a236d0dff0040620300092ae0d85d5ef4c3f67802000000410abeabf007c1247961d2acd133393fafea89af19ee6fb6d90000000000000037eb13c117f5099289a43abbd5a173fef04047db980c0cb84c6a1930f3b9c6141e30be5115de001a8c1431ed0000b103000952e3b250dd8600d6ed02000000c1ff84e95f9a73d760b37e444056b74867fcd8a382e13cc110000000000000003998741bf1f6806b26bc8496f4efbccd52ca36b27b827c2dfb6f1f055e72c3a4d8765152cab016191b45807600c0ff03000a016cc42d7fd00b16f45102000000e03f401bd7d2484a323ecd4b6bf9945a1a35de61a442355102000000000000003eb2df22382e43f5b527c0a6b8b230bccb93947043b7f9357ad3f6591f2897498e6ae2522cf50119a2ca673500804e04000a100bbd541d5a61923e1d020000006653331789442da38ff405a9f3807c7d3407a7e085b5e90e0000000000000000c5652bd21f27a0873515c5a538fc741ee61201d72413c1856e0986707ce3604dee798053422869186bda24f300409d04000a6d82e3c93a69c3f49d40020000000f6af938320a7efb354df9da98f3e5c0a1de0715a2d107160000000000000000baba50a2116b65022b437a9c912c83d18c39a161d88d5d261011413c79570b735087245493b81f1869e5702b0000ec04000b01c8cf1d42683da610ee6002000000dc0ae15cad873162f27db2ff33d9fbe2193aa492e1e9d1050000000000000000339167c2bdf04f5aa7aa56b1ab8925619e7d851e2586d771c519402c640ed5e7dfd4d85487bb1818649c7a5200c03a05000b0495913a4601568a789d0902000000063c2ef9016bf32a904eead62a7cc120cffa3cf243197206000000000000000018b6461deb0d4d9fc9c663a101474332aeaaf7750cc7b003fb71e0494e503d8c2e9d8f558e41161826b07eda00808905000b07fe7cdecae05f1402ff94";

We're not aware about params required to be updated to integrate different blockchain. We just updated dnsSeeds and publicKeyAddressVersion param value.

App Crashes when blockchain download is (nearly) done

Steps to reproduce:

  1. Create Parameters with Main Net
  2. Create a seed from mnemonic and iso date (seed has balance, transactions and two accounts)
  3. Create store with parameters
  4. Create wallet with seed and parameteres
  5. Create downloader with store and wallet
  6. Create peer group with paramteres
  7. Start connections on peer group
  8. Start download on peer group

App will crash when download is finished or nearly finished

2016-09-29 09:27:58.525635 Mana[1394:355331] *** Terminating app due to uncaught exception 'IllegalArgument', reason: 'No implicit path set, call saveToPath: first'
*** First throw call stack:
(0x18316c1c0 0x181ba455c 0x18316c094 0x1000e3d2c 0x1000edfe4 0x1000f1c2c 0x1000f13b8 0x1000d3a38 0x1000cdc28 0x10011da90 0x100112b64 0x100cf125c 0x100cf121c 0x100cfeb54 0x100cf4ce4 0x100cff0f0 0x100d00e6c 0x100d00bb8 0x1821fd2c8 0x1821fcdb4)

libc++abi.dylib: terminating with uncaught exception of type NSException

  • thread #2: tid = 0x56c03, 0x000000018213a014 libsystem_kernel.dylib__pthread_kill + 8, queue = 'WSPeerGroup', stop reason = signal SIGABRT frame #0: 0x000000018213a014 libsystem_kernel.dylib__pthread_kill + 8
    frame #1: 0x0000000182201460 libsystem_pthread.dylibpthread_kill + 112 frame #2: 0x00000001820ae3f4 libsystem_c.dylibabort + 140
    frame #3: 0x0000000181b792d4 libc++abi.dylibabort_message + 132 frame #4: 0x0000000181b96cc0 libc++abi.dylibdefault_terminate_handler() + 304
    frame #5: 0x0000000181ba4844 libobjc.A.dylib_objc_terminate() + 124 frame #6: 0x0000000181b9366c libc++abi.dylibstd::__terminate(void (*)()) + 16
    frame #7: 0x0000000181b92f84 libc++abi.dylib__cxa_throw + 136 frame #8: 0x0000000181ba4690 libobjc.A.dylibobjc_exception_throw + 364
    frame #9: 0x000000018316c094 CoreFoundation`+[NSException raise:format:arguments:] + 104
    • frame #10: 0x00000001000e3d2c ManaWSExceptionCheck(condition=NO, name=@"IllegalArgument", format=@"No implicit path set, call saveToPath: first") + 136 at WSErrors.m:60 frame #11: 0x00000001000edfe4 Mana-[WSHDWallet save](self=0x0000000174151930, _cmd="save") + 80 at WSHDWallet.m:672
      frame #12: 0x00000001000f1c2c Mana-[WSHDWallet registerTransaction:didGenerateNewAddresses:batch:](self=0x0000000174151930, _cmd="registerTransaction:didGenerateNewAddresses:batch:", transaction=0x0000000170470fc0, didGenerateNewAddresses=NO, batch=NO) + 1708 at WSHDWallet.m:1144 frame #13: 0x00000001000f13b8 Mana-[WSHDWallet registerTransaction:didGenerateNewAddresses:](self=0x0000000174151930, _cmd="registerTransaction:didGenerateNewAddresses:", transaction=0x0000000170470fc0, didGenerateNewAddresses=NO) + 88 at WSHDWallet.m:1095
      frame #14: 0x00000001000d3a38 Mana-[WSBlockChainDownloader handleReceivedTransaction:](self=0x0000000174123340, _cmd="handleReceivedTransaction:", transaction=0x0000000170470fc0) + 432 at WSBlockChainDownloader.m:956 frame #15: 0x00000001000cdc28 Mana-[WSBlockChainDownloader peerGroup:peer:didReceiveTransaction:](self=0x0000000174123340, _cmd="peerGroup:peer:didReceiveTransaction:", peerGroup=0x000000017416e640, peer=0x0000000170114250, transaction=0x0000000170470fc0) + 136 at WSBlockChainDownloader.m:492
      frame #16: 0x000000010011da90 Mana-[WSPeerGroup peer:didReceiveTransaction:](self=0x000000017416e640, _cmd="peer:didReceiveTransaction:", peer=0x0000000170114250, transaction=0x0000000170470fc0) + 444 at WSPeerGroup.m:672 frame #17: 0x0000000100112b64 Mana__27-[WSPeer receiveTxMessage:]_block_invoke((null)=0x0000000170856320) + 92 at WSPeer.m:650
      frame #18: 0x0000000100cf125c libdispatch.dylib_dispatch_call_block_and_release + 24 frame #19: 0x0000000100cf121c libdispatch.dylib_dispatch_client_callout + 16
      frame #20: 0x0000000100cfeb54 libdispatch.dylib_dispatch_queue_serial_drain + 1136 frame #21: 0x0000000100cf4ce4 libdispatch.dylib_dispatch_queue_invoke + 672
      frame #22: 0x0000000100cff0f0 libdispatch.dylib_dispatch_queue_override_invoke + 496 frame #23: 0x0000000100d00e6c libdispatch.dylib_dispatch_root_queue_drain + 584
      frame #24: 0x0000000100d00bb8 libdispatch.dylib_dispatch_worker_thread3 + 140 frame #25: 0x00000001821fd2c8 libsystem_pthread.dylib_pthread_wqthread + 1288
      frame #26: 0x00000001821fcdb4 libsystem_pthread.dylib`start_wqthread + 4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.