Brainwallet Core is the free, open-source SPV wallet engine that powers Brainwallet, a self-custodial Litecoin wallet. It's a fork of breadwallet-core retargeted from Bitcoin to Litecoin, written in portable C99 so it can be embedded directly in both the Android and iOS apps.
This library ships embedded (as a git submodule / vendored source) in both Brainwallet apps — it is not distributed or installed on its own:
- Android: gruntsoftware/android (
app/src/main/jni/core) - iOS: gruntsoftware/ios (
Modules/core)
- Android Repo: gruntsoftware/android
- iOS Repo: gruntsoftware/ios
- Website: brainwallet.co
- Support: brainwallet.co/support
Standalone, not a client of our servers. This library implements SPV (simplified payment verification) — it connects directly to the Litecoin peer-to-peer network to sync headers/merkle blocks and broadcast transactions, with no Brainwallet-run backend in the loop for balances or broadcasting.
Deterministic recovery. BIP32 hierarchical-deterministic wallet logic (BRBIP32Sequence.c) means one seed phrase recovers the full balance and transaction history on any device, forever.
Keys never leave the device. Key generation, signing, and storage handoff all happen locally (BRKey.c, wrapping secp256k1) — this library has no network path that could exfiltrate a private key, and no custody of user funds.
Built on open standards, not a proprietary protocol:
- SPV for fast sync without running a full node
- BIP32 deterministic wallets
- BIP38 import of password-protected paper wallets (
BRBIP38Key.c) - BIP39 mnemonic seed phrases (
BRBIP39Mnemonic.c) - BIP70 payment protocol support (
BRPaymentProtocol.c)
- Full SPV sync engine: peer discovery/selection, bloom filters, merkle block download and chain reorg handling (
BRPeerManager.c) - Dual-peer "privacy shield" — an addition on top of upstream breadwallet-core: an optional second, differently-filtered peer cross-validates block/transaction data to detect a peer lying by omission and to obscure which bloom-filter matches are real
- Adaptive bloom filter false-positive rate tuning based on observed tx volume
- BIP32 HD wallets, BIP38 encrypted keys, BIP39 mnemonics, BIP70 payment requests
- Hardcoded Litecoin mainnet/testnet chain parameters and checkpoints (
BRChainParams.h)
- A C99 compiler (
gccorclang) andmake - This repo uses a git submodule for
secp256k1— clone withgit clone --recurse-submodules, or rungit submodule update --init --recursiveafter a normal clone - The
secp256k1submodule must stay pinned at commitb408c6a— later upstream commits removedsecp256k1/src/basic-config.h, whichBRKey.cdepends on directly; CI verifies this pin
make # build the test binary (mainnet)
make test # build and run tests (mainnet)
make testnet # build and run tests against Litecoin testnet
make clean # remove build artifacts
- Primitives:
BRInt.h(fixed-width int/hash types),BRArray.h(growable-array macros),BRSet.h(hash set),BRCrypto.c(SHA/RIPEMD/AES/ChaCha20/Poly1305) - Keys & encoding:
BRKey.c(EC keys viasecp256k1),BRBase58.c,BRBech32.c,BRBIP32Sequence.c,BRBIP38Key.c,BRBIP39Mnemonic.c - Chain data model:
BRAddress.c,BRTransaction.c,BRMerkleBlock.c,BRBloomFilter.c - Chain parameters:
BRChainParams.h— mainnet/testnet DNS seeds, magic numbers, and checkpoints - Wallet:
BRWallet.c— UTXO/balance tracking, transaction creation and fee logic - Networking / SPV sync:
BRPeer.c(peer wire protocol) andBRPeerManager.c(sync engine, the largest file in the repo) - Payment protocol:
BRPaymentProtocol.c
Everything is plain C with opaque structs and New/Free pairs (e.g. BRPeerManagerNew/BRPeerManagerFree) — callbacks are wired in explicitly, with no hidden global state.
test.c compiles into a single test_runner binary driven by BRRunTests(), covering every module. CI runs on CircleCI (.circleci/config.yml) with a mainnet build, a testnet build, and a separate AddressSanitizer build.
Found a security vulnerability? Please do not open a public issue — report it via brainwallet.co/support, clearly marked as a security report. Since this library ships embedded in both apps, reports about it are handled under the same disclosure process described in the Android and iOS repos' SECURITY.md.
Brainwallet Core is released under the MIT License, inherited from the original breadwallet-core (Copyright (c) 2015 breadwallet LLC).
Brainwallet Core is a fork of breadwallet-core, originally written by Aaron Voisine (@voisine) — co-founder of BRD (formerly Breadwallet) and creator of the open-source SPV wallet code that now powers millions of users across BRD, Litewallet, and Brainwallet. Aaron's original wallet-core design is the foundation this library builds on, retargeted here from Bitcoin to Litecoin and extended with features like the dual-peer privacy shield.
In June 2026, Aaron joined Brainwallet as an investor and advisor — see the press release for details.
For the full, up-to-date changelog see GitHub Releases and the compare view. Highlights from recent versions:
BRChainParams.hfailed to compile under GCC (initializer element is not constant) — GCC only accepts a compound-literal static initializer when it's an object's entire initializer, not nested inside the checkpoint tables' larger aggregate initializer. Addeduint256_init(), a bare brace-list variant with no such restriction.
- The three test failures carried as "known issues" from v10.3.0 (
BRKeyTests,BRBIP32SequenceTests,BRMerkleBlockTests) turned out to be leftover Bitcoin-mainnet fixtures from this fork's breadwallet-core origin — Litecoin's code was correctly rejecting them, but the tests never checked the return value. Converted every fixture to genuine Litecoin-derived vectors and re-enabledBRBIP38KeyTests, which had been permanently disabled instead of fixed. - Renamed
BITCOIN_PUBKEY_ADDRESS/BITCOIN_SCRIPT_ADDRESS/BITCOIN_PRIVKEY(+ testnet variants) toLITECOIN_*— same values, but the old naming is exactly what made the fixture bugs above easy to introduce and hard to notice for 8 years.
- Strict-aliasing miscompilation under GCC in
UIntNSetBE()/UIntNSetLE()(BRInt.h) — used throughout wire-format serialization (transactions, blocks, peer protocol). Found by reproducing against real GCC locally; GCC's optimizer was silently dropping a write due to a pointer-cast aliasing violation. Fixed by writing byte-by-byte instead. - Two more genuine UB bugs found along the way: a
memcpy()with aNULLsource inBRHMACDRBG(), and an unaligned/aliasing pointer cast inBRMurmur3_32(). - Several real memory leaks, including one in
BRWalletCreateTransaction()/BRWalletCreateOpsTransaction()/BRWalletFeeForTxAmount()affecting every successful call to the most commonly used function in the wallet API.
Full Changelog: https://github.com/gruntsoftware/core/compare/v10.3.0...v10.4.0
v10.3.0 [PR #17]
- Native SIGSEGV crash (
BRPeerManagerLastBlockHeight, offset0xb8) —BRPeerManagerRescan()assignedBRSetGet()'s result directly tomanager->lastBlockwith noNULLcheck; when a checkpoint block wasn't found in the block set this crashed every subsequent accessor. Root-caused from a symbolicated Firebase Crashlytics tombstone (issuea82fa4956025d87609f0f8ba2e87a11d, regressed) that pointed at the exact function and byte offset.BRPeerManagerRescan()now keeps the previouslastBlockinstead of nulling it out on a lookup miss, and all four public accessors that readlastBlockare now guarded as defense in depth. - Added
BRPeerManagerSetIntegrityWarningCallback()so embedding apps can route these recovered-from states into their own crash/analytics tooling.
BRTransactionTests()had a duplicatedBRTransactionCopytest block causing a compile error; removed.test.cguardedmain()with#ifndef BITCOIN_TEST_NO_MAIN, which only checks definedness (not value) against the Makefile's-DBITCOIN_TEST_NO_MAIN=0, always excludingmain(). Fixed to#if !BITCOIN_TEST_NO_MAIN.make testnow builds, links, and runs end-to-end for the first time.
Full Changelog: https://github.com/gruntsoftware/core/compare/v10.2.0...v10.3.0
- Reset the default bloom filter false-positive rate (FPF)
- Removed non-SPV peers from the hardcoded peer list; rate/fee handling updates
v10.1.1 / v10.1.0 [PR #9]
fix: filter out rejected txfix: set r = 1, update error label— smallBRPeerManagertest fix
v10.0.1 – v10.0.0 [PR #6]
- Changes to meet iOS 18.4.1 linking requirements
techdebt: fix disconnect behavior revert
v4.2.0 [PR #5]
To improve peer discovery, added support for selected peers sourced from api.blockchair.com/litecoin/nodes:
- Increased
PEER_MAX_CONNECTIONSto 8 - Added
isFeatureSelectedPeersOntoggle andselectedPeerIPs - Added
_BRPeerManagerFindPeersV2to parse and populatemanager->peers
- Re-added the missing module map file
- Re-instated git submodules, fixed disconnect behavior
- Initial retargeting from
breadwallet-core/brainwallet-coreferences togruntsoftware/core