Author

Topic: Handling branches (Read 724 times)

sr. member
Activity: 528
Merit: 368
January 08, 2017, 08:35:50 PM
#4
The main reason for choosing btcd and btcwallet was their clean separation between Bitcoin node and wallet. However, I would be comfortable using bitcoind in production as well.
s2
full member
Activity: 198
Merit: 123
January 08, 2017, 08:33:16 AM
#3
Thanks for the reply, it's incredibly reassuring to hear other real world implementations.

Do you mind me asking, why did you use btcd rather than bitcoind?

I'm nervous bitcoind isn't actually suitable for commercial applications because there are so many alternatives floating around... it's rather bewildering knowing what is sensible and where to start.
sr. member
Activity: 528
Merit: 368
January 06, 2017, 03:17:51 PM
#2
My solution is slightly different as I don't use my Bitcoin node's wallet functionality but hopefully it is of value to you anyways.

Whenever a new block is added to the chain my application fetches it from the node and scans it for spendable outputs. Any such outputs are written to the database, as well as the block's height and hash.

A fork means that one or more of the blocks that we previously processed are no longer part of the chain. My Bitcoin node (btcd) provides a notification hook for this specific event, but the same can be achieved with bitcoind's more general blocknotify.

When a fork occurs, we need to find the common ancestor and mark all previously processed blocks up to that point as invalid. To do this we step backwards through the (old) chain, starting at the last block in the database considered to be valid. For every block, we query the Bitcoin node to find out if it is valid, i.e. part of the new chain. If it is invalid, we mark it as such in the database and move on to its parent. If it is valid, we've found the common ancestor.

Then we query the node for the common ancestor's (new) child block, process it and move on to its child. We repeat this for the child until a block has no child, which means we have reached the end of the new chain and are synchronized with the network again.

In this way even larger forks are properly handled. Spendable outputs can be retrieved by the database at any time with a query such as:

Code:
SELECT txid, vout, value
FROM outputs INNER JOIN blocks ON outputs.block=blocks.hash
WHERE blocks.valid=true AND outputs.spent=FALSE;

I hope this helps. If something doesn't make sense yet, let me know and I'll try to clarify!
s2
full member
Activity: 198
Merit: 123
January 06, 2017, 02:38:16 PM
#1
I'm trying to keep track of funds that have come in on the bitcoind client but I'm not sure I'm handling the forking issue well so looking for some advice.

What I'm currently doing is when a tx comes in, I store it in my own DB from the walletnotify option that calls my script.
When the tx is confirmed it also calls my script again and I update my db saying it has now been confirmed and can be spent. 
The funds are at a later date forwarded on to coldstorage to prevent any easy hacks.

The catch is, what happens when a fork happens.  At the moment I need to go through and reverse all the transactions that are now in the now orphaned blocks.  This seems a real headache!
I mean do I have to go through and detect that the fork has changed and now reverify EVERY transaction that has ever happened since the dawn of time (or perhaps track which block each transaction was found in)?  What if I've already confirmed it and allowed the funds to be moved, seems like things are going to get complicated quickly.


So my question is, how are enterprise solutions already handling forks and transactions that have previously been ear marked as confirmed and able to spend?



Jump to: