The main function of the ord node is to parse Bitcoin transaction data into plaintext according to the ordinals protocol. However, due to the finality of the POW consensus protocol of Bitcoin, data may be rolled back due to block reorganization. When a block rollback occurs, the parsed data of the rollback block by the ord node has been written to the disk, and there is no way to clean up the invalid data due to the block rollback, so the ord node cannot continue to parse the block and can only stay at a certain height.
If the Bitcoin node produces a block 00000000000000000005ae2d26e36788a3f4f2770495c5c6cf2e2e75cf8ec33c
at a height of 9999, but then a longer chain appears, and the block at the height of 9999 is 0000000000000000000266ef9c0057fa9ca62f4d1e701070e3025a217829b3c1
, then the data in the block 00000000000000000005ae2d26e36788a3f4f2770495c5c6cf2e2e75cf8ec33c
is no longer valid. The data generated by the ord node parsing this block all need to be deleted, otherwise the subsequent plaintext data will be confused.
Because the ord node ensures that the plaintext data is up-to-date, it will parse the block of the latest height in real time and write it to the disk. When a block rollback occurs, the only solution to clean up the invalid data is to re-parse all blocks from the beginning. Or we can regularly backup data, and when a rollback occurs, we can stop the ord node and re-synchronize from the backup data, but obviously this is not a perfect solution. If this process can be automated, it will be a satisfactory solution.
In order to achieve automatic data rollback, we have introduced the savepoint function of redb, which can be understood as a data backup at the memory level. Theoretically, the rollback of Bitcoin will not exceed 6 blocks, so we can make a savepoint every 3 blocks, and keep up to 4 savepoints, so that at least the data can be backed up to 10 heights ago. The specific process is as follows:
Make a savepoint when the node starts.
Check the block height n
saved in the db, and request the block with a height of n+1
from the Bitcoin node.
Every time a new block with a height of n
is queried, compare whether block{n}.header.prev_blockhash
is consistent with block{n-1}.hash
. If it is consistent, go to step d, otherwise, it means that a block reorganization has occurred and go to step e.
If the current height is a multiple of 3, make a savepoint. If the current number of savepoints made exceeds 4, delete the oldest savepoint.
Restore the data with the latest savepoint, and then return to step b.
Since the ord node only has the possibility of encountering block reorganization problems when it is synchronized to the latest height of the Bitcoin node, a fast-sync
mode judgment is introduced. When the ord node lags behind the Bitcoin node by more than 10 blocks, it is considered that the ord node is in fast-sync
mode. In order to catch up with the latest height as soon as possible, savepoints will not be made.
During development, data rollback is considered as an independent feature of the ord node, so it should be enabled through the Rust feature parameter --features=rollback
. When this parameter is not configured, the rollback feature will not take effect.