Right. I created this as the first step in building an Android client
actually, but for various reasons will probably focus on the library
aspect for now. I don't have any Android code, but the inclusion of
the Bouncy Castle lightweight API should make it easier to run there.
--
GMail Engineering
Google Switzerland GmbH
I just uploaded a first (non-functional) version to Google Code:
http://code.google.com/p/bitcoin-wallet/
I have some problems:
1) As there is no bitcoin node running on localhost on Android devices,
I need at least one peer somewhere else. Currently I have hardcoded a
machine from my local network, but ideally the App should be able to
discover peers on its own. Is there any support present or planned for
this in bincoinj?
2) If I invoke peer.startBlockChainDownload(), Android runs out of
memory quite quickly. There is only 4 MB of heap availble per app on
some devices. Is there any way to limit the download process? Can I
detect receiving Bitcoins without downloading the block chain somehow?
3) Also, I think some listeners/callbacks are missing to get some status
about the download. For starters, I'd like to display the number of
received blocks like in the desktop client.
4) [not related to bitcoinj] I'm not sure where to store the wallet.
"filesDir" is probably the safest and most secure place on an Android
device but still if the user clears all data for an app, the wallet is
gone. On the other hand, external storage (e.g. SD-cards) can be read by
all apps. In general, Android is an insecure platform because there are
next-to-none security updates and vulns go unpatched for months (even if
you own a Google Phone). So a client-based wallet would only be good for
small amounts of money.
Best regards,
Andreas
As you have discovered, this is a v0.1 release for a reason :-)
On Tue, Mar 8, 2011 at 12:40 PM, Andreas Schildbach
<and...@schildbach.de> wrote:
> 1) As there is no bitcoin node running on localhost on Android devices,
> I need at least one peer somewhere else.
Yes. I'll probably check in a list of seed nodes at some point.
> 2) If I invoke peer.startBlockChainDownload(), Android runs out of
> memory quite quickly.
That's because we keep every block header around in expanded form even
when we no longer really need them. Even keeping them in serialized
form would be insufficient as the headers alone are around 5mb per
year.
The handling of the block chain will be changing a lot in future. This
is one of the problems that'll get fixed.
> 3) Also, I think some listeners/callbacks are missing to get some status
> about the download. For starters, I'd like to display the number of
> received blocks like in the desktop client.
It's probably not necessary. The only reason the client shows the
number of blocks is because the download is so slow. But we can make
the initial download much faster by using getheaders and checkpoints.
An Android app should wake up occasionally and catch up with the block
chain when the phone is in your pocket so it never has far to go when
you need it.
> 4) [not related to bitcoinj] I'm not sure where to store the wallet.
Internal storage is the right place. In the longer run, using the
backup framework to store an encrypted version server side is the way
to go. See the notes I put in this thread:
http://www.bitcoin.org/smf/index.php?topic=3017.msg42069#msg42069
For security, we'll see how this plays out in the longer term. The
alternative is desktop operating systems which don't even try to stop
apps stealing your wallet. At least on Android (and other mobile
platforms) such an ability is unquestionably a bug.
I just imported the seed nodes from the official client, so there is a
starting point.
> The handling of the block chain will be changing a lot in future. This
> is one of the problems that'll get fixed.
Great to hear. I'm happy to adapt to any API changes this might involve.
>> 3) Also, I think some listeners/callbacks are missing to get some status
>> about the download. For starters, I'd like to display the number of
>> received blocks like in the desktop client.
>
> It's probably not necessary. The only reason the client shows the
> number of blocks is because the download is so slow.
Well ok for debugging it would be nice but on the other hand I can just
put some debug statements into bitjoinj myself (-:
> Internal storage is the right place. In the longer run, using the
> backup framework to store an encrypted version server side is the way
> to go.
This is a good idea.
I just discovered that you (accidently?) used some Java6 API, e.g.
usage of peekLast() on LinkedList in
BlockChain.getTopBlock(BlockChain.java:235) and other places.
This makes your library incompatible to at least Android 2.2 and below.
Strangely, I did not have any problems on my Android 2.3.3-upgraded
Nexus One, is it possible that Android 2.3 contains Java6 API now?
Regards,
Andreas
That's true. I don't mind adding some kind of listener interface on
the block chain. The version message contains the peers chain height
too, so we can also calculate a completion percentage.
> This makes your library incompatible to at least Android 2.2 and below.
> Strangely, I did not have any problems on my Android 2.3.3-upgraded
> Nexus One, is it possible that Android 2.3 contains Java6 API now?
Probably. I'll see if I can make IntelliJ warn me about that and fix them.
http://code.google.com/p/bitcoinj/
http://code.google.com/p/bitcoin-wallet/
I just sent you some testnet bitcoins.
E/AndroidRuntime(14118): FATAL EXCEPTION: main
E/AndroidRuntime(14118): java.lang.Error: blockstore cannot be created
E/AndroidRuntime(14118): at de.schildbach.wallet.Application.onCreate(Application.java:57)
E/AndroidRuntime(14118): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
E/AndroidRuntime(14118): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3272)
E/AndroidRuntime(14118): at android.app.ActivityThread.access$2200(ActivityThread.java:117)
E/AndroidRuntime(14118): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:969)
E/AndroidRuntime(14118): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(14118): at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime(14118): at android.app.ActivityThread.main(ActivityThread.java:3683)
E/AndroidRuntime(14118): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(14118): at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime(14118): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime(14118): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime(14118): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(14118): Caused by: com.google.bitcoin.core.BlockStoreException: Could not connect 36dcfb099071e9eb71f5b5b55448db0e9d1677387328473ec9ce89cb7bc5af26 to 0000000191a1fef57010c1189bad65eff5e99596187d7802e24f4693800bcb02
E/AndroidRuntime(14118): at com.google.bitcoin.core.DiskBlockStore.load(DiskBlockStore.java:112)
E/AndroidRuntime(14118): at com.google.bitcoin.core.DiskBlockStore.<init>(DiskBlockStore.java:43)
E/AndroidRuntime(14118): at de.schildbach.wallet.Application.onCreate(Application.java:53)
E/AndroidRuntime(14118): ... 12 more
W/ActivityManager( 7192): Force finishing activity de.schildbach.wallet/.WalletActivity
W/dalvikvm(14133): threadid=1: thread exiting with uncaught exception (group=0x40015560)
E/AndroidRuntime(14133): FATAL EXCEPTION: main
E/AndroidRuntime(14133): java.lang.Error: blockstore cannot be created
E/AndroidRuntime(14133): at de.schildbach.wallet.Application.onCreate(Application.java:57)
E/AndroidRuntime(14133): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
E/AndroidRuntime(14133): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3272)
E/AndroidRuntime(14133): at android.app.ActivityThread.access$2200(ActivityThread.java:117)
E/AndroidRuntime(14133): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:969)
E/AndroidRuntime(14133): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(14133): at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime(14133): at android.app.ActivityThread.main(ActivityThread.java:3683)
E/AndroidRuntime(14133): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(14133): at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime(14133): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime(14133): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime(14133): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(14133): Caused by: com.google.bitcoin.core.BlockStoreException: Could not connect 36dcfb099071e9eb71f5b5b55448db0e9d1677387328473ec9ce89cb7bc5af26 to 0000000191a1fef57010c1189bad65eff5e99596187d7802e24f4693800bcb02
E/AndroidRuntime(14133): at com.google.bitcoin.core.DiskBlockStore.load(DiskBlockStore.java:112)
E/AndroidRuntime(14133): at com.google.bitcoin.core.DiskBlockStore.<init>(DiskBlockStore.java:43)
E/AndroidRuntime(14133): at de.schildbach.wallet.Application.onCreate(Application.java:53)
E/AndroidRuntime(14133): ... 12 more
W/ActivityManager( 7192): Force finishing activity de.schildbach.wallet/.WalletActivity
W/ActivityManager( 7192): Activity pause timeout for HistoryRecord{40a28dc8 de.schildbach.wallet/.WalletActivity}
W/ActivityManager( 7192): Activity destroy timeout for HistoryRecord{40a28dc8 de.schildbach.wallet/.WalletActivity}
why are you both doing svn instead of git or hg? contributions are so much easier for both sides.