novitski / bitcoinj

Automatically exported from code.google.com/p/bitcoinj
Apache License 2.0
0 stars 0 forks source link

BlockChain reset #162

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
In addition to the much discussed BlockChain rewind feature we need something 
that can hard-reset a BlockChain to genesis (or perhaps a snapshot) in a clean 
way.

Currently this is very difficult, because BlockChain and BlockStores keeps 
state (chain head, cached headers) that would need to be cleared out.

I'd propose some method on BlockChain that properly serializes access with all 
Peer threads potentially running and clears out all state including BlockStore 
files.

I know that ideally there is no need for this usecase, but reality is 
different: We've got lots of corrupt blockchains out in the wild and no 
reliable way to repair/reset them.

Original issue reported on code.google.com by andreas....@gmail.com on 22 Mar 2012 at 12:00

GoogleCodeExporter commented 9 years ago
I'm not sure what the feature would be. You can reset the block chain/store by 
simply deleting the underlying file, clearing the wallet, and redownloading it.

It's up to the library user (you) to ensure that there's only one 
BlockChain/BlockStore object per app. Otherwise all kinds of things can go 
wrong. We could potentially add some file locking to the BlockStore 
implementations to catch cases where this invariant is broken.

Original comment by hearn@google.com on 22 Mar 2012 at 12:08

GoogleCodeExporter commented 9 years ago
The usecase is resetting the blockchain from within the app (by the user), in 
whatever state the app currently is (e.g. happily downloading). I cannot 
"simply delete the underlying file", becaue it can be in access by the block 
store. And the block store can have other state that needs to be cleared out as 
well.

Original comment by andreas....@gmail.com on 22 Mar 2012 at 12:18

GoogleCodeExporter commented 9 years ago
AFAIK the only reliable way to do this right now, is setting some flag from 
within the app (e.g. preferences) and then intentionally crash the app. This 
will make sure all memory state goes away. Upon restart, the app detects the 
flag before instantiating the block store and removes the file as well.

However, crashing the app is inherently dangerous to other components, e.g. 
wallets.

Original comment by andreas....@gmail.com on 22 Mar 2012 at 12:21

GoogleCodeExporter commented 9 years ago
I think what you actually want is the ability to stop the library controlled 
threads in an effective manner, as discussed on the other bug. If there are no 
library-controlled threads running then to reset the chain all you have to do 
is  close the block store (we should add a method for this) and re-create all 
the objects from scratch. Now you have fresh in memory state. The old state 
will be GCd away shortly afterwards.

Original comment by hearn@google.com on 22 Mar 2012 at 12:23

GoogleCodeExporter commented 9 years ago
While the stopping ability would be nice indeed, I'm not sure if its really 
necessary for this usecase. But yes, it would be a possibility as well.

Original comment by andreas....@gmail.com on 22 Mar 2012 at 12:37

GoogleCodeExporter commented 9 years ago
And remember we also need that rewind feature. And we need that without 
re-creating blockstores and restarting threads I'd say.

If I happen to request a rewind to the genesis block, the blockchain might 
decide it's easier to just start from scratch. And bingo, the reset feature 
would already be there... (-:

Original comment by andreas....@gmail.com on 22 Mar 2012 at 12:41

GoogleCodeExporter commented 9 years ago
I spent a couple of days without success trying to "wipe" the internal state of 
the Peers for the blockchain replay I do in MultiBit.   In the end I found it 
most reliable to:
1) Have a custom org.multibit.store.ReplayableBlockStore with a method to set 
the chainhead, clear the internal caches and physically truncate the blockstore.
2) Stop the PeerGroup.
3) Wait for notification of zero Peers.
4) Restart the PeerGroup
5) Download from the new chainhead.

It is in github in the v0.3 branch in 
org.multibit.network.MultiBitService#replayBlockChain(Date dateToReplayFrom) 

That seems to work pretty reliably and could take it back to the genesis block 
if required.

Original comment by jimburto...@gmail.com on 22 Mar 2012 at 2:17

GoogleCodeExporter commented 9 years ago
@Jim Thanks, your 1) is more or less what I have in mind for BlockStore, but 
let me ask a question: Miron told me that BlockChain serializes access rather 
than BlockStore, so how do you make sure that while your are resetting your 
BlockStore no other threads are concurrently accessing BlockStore?

Original comment by andreas....@gmail.com on 22 Mar 2012 at 2:51

GoogleCodeExporter commented 9 years ago

Original comment by hearn@google.com on 8 Jan 2013 at 4:41

GoogleCodeExporter commented 9 years ago
Recently a Wallet.reset() method was added. I think this is all we can do, 
except the ability to roll back the blockchain while keeping PeerGroup up. If 
we don't plan to support that, I think we can/should close this issue. Any 
objection?

Original comment by andreas....@gmail.com on 6 Jan 2015 at 11:39

GoogleCodeExporter commented 9 years ago
For WalletTemplate/Lighthouse, I simply shut down the WalletAppKit and then 
restart it in such a way that it wipes the block chain file.  It didn't seem 
all that hard and works well enough. Actually that reminds me - we should check 
that WAK actually uses the new reset method :)

Original comment by mh.in.en...@gmail.com on 6 Jan 2015 at 1:38