Connect Android SPV Bitcoin Wallet with permissioned Multichain blockchain

+7 votes

Hi all,

I need to connect an Android SPV Wallet (e.g. this one) with a Multichain private permissioned blockchain. The application requirements are that permissions and streams of the Multichain blockchain should be leveraged, while we don't need the assets feature. I found that one should change these blockchain parameters so as to use a permissioned Multichain blockchain with a mobile wallet instead of a Bitcoin chain.

Some relevant questions:

  1. Are these the only changes to be done to make it work? 
  2. Is there any step-by-step guide to achieve the connection flawlessly?
  3. Would you suggest another Android SPV Wallet? e.g. can this forked library work fine with Android mobile devices? (I plan to install and test the wallet on an android tablet, and then on an android smartphone).

Many thanks in advance for your responses!

Regards,

Natassa

 

asked Aug 17, 2017 by Natassa Theodouli

1 Answer

+2 votes

First, we've updated those instructions to allow the use of more recent MultiChain protocol versions.

I'm afraid we don't yet have concrete step-by-step suggestions on how to do this, beyond what is written on that page. But if you stick to non-asset transactions the wallet should be highly compatible with minimal changes.

In terms of streams, you would need to add functionality to the to read data from the stream. You can use the bloom filtering in the bitcoin p2p protocol to detect patterns of the stream data, which is formatted as written here:

https://www.multichain.com/developers/data-streams/

answered Aug 18, 2017 by MultiChain
Many thanks for your answer! In order to connect breadwallet-android mobile SPV wallet with a private Multichain I have set up on my localhost, I need to change the list of DNS seeds, the blockchain checkpoints, and the version, verack, and verackack messages exchanged by the local and remote peer during the handshaking.

Some relevant questions:
1) As regards dns seeds should I just add the IP of the node where the chain runs? I.e. same as the IP in nodeaddress field in the JSON response in the nodeifo API call?
2) What should I add as blockchain breakpoints in the case of private Multichain node instead of the Bitcoin network?
3) What is the correct answer for the version protocol, verack, and verackack messages sent by the remote peer? (As a workaround, I plan to completely disable the message checks in the wallet code, but I'm not sure if this is going to work properly...). Thank you in advance for your response!
If your blockchain has anyone-can-connect=true, you don't need to modify the handshaking procedure, and MultiChain will accept bitcoin protocol handshakes.

1) You can add the IP addresses of multiple MultiChain nodes. This can be the same IP address as in the nodeaddress, or any other IP address on which those servers can receiving incoming connections.

2) You should remove checkpoints from the wallet code completely, unless you want to set some based on the MultiChain blockchain (I'm guessing the checkpoints consist of a block height and hash, which you can extract from MultiChain using listblocks or getblock).

3) The protocol is from the protocol version of the MultiChain blockchain (1000x). As for the verack and verackack, unfortunately we don't yet have this documented so you would need to take a look at the MultiChain source code to see their contents.
Hi again, I have some more questions regarding checkpoints (#2 in comment above).
1) I need to set some checkpoints based on my private Multichain. To do so, in the wallet I need to set block height, block hash, block timestamp, and block target.
If I use listblocks, I can take the first three, but I can't see how to get the block target. Can you help me on how to find the block target for the blocks that I will use as checkpoints? Is there any JSON RPC command, or can I find it somehow in the blockchain params.dat file?

2) Which/how many blocks should I use as checkpoints? My chain has 59 blocks (starting from the genesis block), is it e.g. ok to use the blocks with the 10 biggest heights (having height 50-59)?
1) I don't know the details of the wallet, but I'm guessing the target is based on the nBits field of the block header, which MultiChain gives you in the "bits" field of the response to the getblock API.

2) Any checkpointed block automatically checkpoints all previous blocks (due to the chain of hashes on which blockchains rely) so just checkpointing the last block is enough to fully fix all previous blocks as well.
Many thanks for your advice! I followed steps above and then tried to connect the mobile wallet with my private Multichain. The mobile wallet started syncing (until 5%) but then sync failed and a message 'not connected' appeared on the screen of the mobile. I searched the debug.log in the private Multichain, and found this error (there appear many peers in the logs, while I tried connection only from one peer, i.e. the mobile SPV wallet, don't know why):
......
2017-08-29 10:39:55 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=71
2017-08-29 10:39:59 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=72
2017-08-29 10:40:03 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=73
2017-08-29 10:40:07 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=74
2017-08-29 10:40:11 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=75
2017-08-29 10:40:15 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=76
2017-08-29 10:40:19 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=77
2017-08-29 10:40:23 mchn: PROCESSMESSAGE: INVALID MESSAGESTART version peer=78
.......
In the wallet app logs I can see that the problem appeared when the wallet sent the version message. I copy the exact app logs below, where the actual IP and port have been replaced by <IP:PORT>
..........
 <IP:PORT> socket connected
 <IP:PORT> sending version
 D Message from C: : getTransactions
 I bread   : <IP:PORT> Connection timed out
 I bread   : <IP:PORT> disconnected
 I bread   : <IP:PORT> sync failed
...................
How could I solve this?
Hi again! I figured what the problem mchn: PROCESSMESSAGE: INVALID MESSAGESTART  was. The magic number was incorrect in the wallet I changed it to 0xd9b4bef9 (this is the equivalent of f9beb4d9 in hex for bitcoin-like handshaking) and then using the bitcoin-style params.dat, I managed to connect the mobile wallet with the private Multichain blockchain.
Many thanks for the support!!
Great - thanks for the update!
Hi,

I tried similar and I think i made good progress (thanks so much for all the help from this thread so far) until the client reports "invalid merkleblock", like so:

---- 8< ----
connecting
10-23 14:33:09.478 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 socket connected
10-23 14:33:09.478 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending version
10-23 14:33:09.652 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got version 70002, useragent:"/Satoshi:0.10.0/"
10-23 14:33:09.653 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending verack
10-23 14:33:09.808 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got verack in 0.330641s
10-23 14:33:09.808 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 handshake completed
10-23 14:33:09.808 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 connected with lastblock: 14349
10-23 14:33:09.819 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending filterload
10-23 14:33:09.820 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 calling getblocks with 1 locators: [50f9e518dbd661adf5ee8ae2f9169bbbb364a82bcbcee81526164de8df320000, ]
10-23 14:33:09.820 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending getblocks
10-23 14:33:09.820 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got getaddr
10-23 14:33:09.820 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending addr
10-23 14:33:09.820 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got ping
10-23 14:33:09.820 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending pong
10-23 14:33:10.000 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got inv with 1 item(s)
10-23 14:33:10.001 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending getdata
10-23 14:33:10.056 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got inv with 2 item(s)
10-23 14:33:10.056 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending getdata
10-23 14:33:10.234 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 got inv with 500 item(s)
10-23 14:33:10.239 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending getdata
10-23 14:33:10.239 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 calling getblocks with 2 locators: [e0f70089603f2b3b966124cc37e65f5820bb0f786361e036285fd99ee03f0000, 68ca777a538ccd7e973e7caae7cd1d66e7136b2cf64dafff8b9f508759c60000]
10-23 14:33:10.240 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 sending getblocks
10-23 14:33:10.387 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 invalid merkleblock: 242e74e61997a80e57ce28763a15db091a3fa5e218356f2dbb1a192383d60000
10-23 14:33:10.388 19506-19963/com.breadwallet I/bread: 10.15.17.11:2897 disconnected
---- 8< ----

I searched quite a bit and could not find anything about "invalid merkleblock".  I think i did set up my checkpoints ok: i took the first block and a later one at height 600:

---- 8< ----
static const struct { uint32_t height; const char *hash; uint32_t timestamp; uint32_t target; } checkpoint_array[] = {
    {      0, "000032dfe84d162615e8cecb2ba864b3bb9b16f9e28aeef5ad61d6db18e5f950", 1508753723, 0x1f00ffff },
    {      600, "000032dfe84d162615e8cecb2ba864b3bb9b16f9e28aeef5ad61d6db18e5f950", 1508759249, 0x1f00ffff }
---- 8< ----

Any ideas?

Thanks!
Hi Willem, I'm not sure whether this will solve your problem, but since any checkpointed block automatically checkpoints all previous blocks, please try to add to the checkpoint_array ONLY the last block (the one with the max height in your chain) and see how it goes.
Thanks Natassa, I'll try that now.

Did you ever get this working?  I'm actually having quite a few issues.  This is but one of them.  I also commented out the code that verifies the block height.
I managed to download the chain in a mobile device in the Android studio emulator. Could you please tell the exact file and lines that you needed to comment out? I assume you refer to the android breadwallet code, don't you?
...