How to get data back on ByzCoin

OK, now it happened – I lost my addressbook on ByzCoin. As we’re using the Partner-login internally, I have a list of all accounts I created on the blockchain. Currently it’s not encrypted using Calypso yet, work in progress. So my account on Byzcoin has a slice of all IDs of all accounts I created. This is useful when a user loses his account and wants it recovered. As long as the user did not remove his trust in me, I can do that using a special recovery-rule in DARCs.

Problem is that I deleted my addressbook šŸ™ It happened when I was working on reviving an old mobile app for use on the blockchain: Proof of Personhood. The nice thing is that you can link the account on the blockchain with the app. The bad thing is that the app deletes the addressbook! Well, fixed that in the meantime. But, too late.

But ByzCoin is a blockchain, so the information is still stored somewhere in the blocks, so let’s recover it.

The ByzCoin Explorer

I wanted to use https://stackblitz.io/github/c4dt/ol-explorer, but for some bitrotting this does not work anymore. The CEO of stackblitz was quite surprised, but, well, it still doesn’t work. So installing it locally and working locally with it:

git clone https://github.com/c4dt/ol-explorer
cd ol-explorer
npm ci
npm start

This is some hacky way to interact with ByzCoin: all the needed libraries are loaded, the test-network of DEDIS is preconfigured, and you can connect to your account on byzcoin. For programming, you can use your preferred IDE with all the automatic completion and documentation that is available. Would be very nice to be able to use stackblitz, so you would not even need to install anything. But welll…

OK, first thing is to connect to your user on byzcoin: supposing you have an account, on the omniledger-demo, choseĀ Add Device and enter some name. Once the device has been added to your account, copy the link, and on localhost:4200 (if yourĀ npm start is still running) click onĀ Attach User and copy the url from the new device.

Getting old Information

Now that the blockchain explorer is linked to our account, we have write-access to it on ByzCoin, so we need to be careful. If we bust it, there might be no way back at all… In the ngOnInit method in src/app/app.component.ts, add the following after theĀ this.logPP…. line.

const versions = await this.bcs.bc.getAllInstanceVersions(this.bcs.user.credStructBS.id);
for (const version of versions){
    this.log(`Version ${version.statechange.version} at block ${version.blockindex} with length ${version.statechange.value.length}`);
}

This will ask one of the nodes to return all known instance-versions and print them out. Unfortunately, this is not a reliable method. The reason is that the nodes do this on a best-effort basis. They don’t need to hold the whole blockchain, as currently about 25 blocks out of the 100’000 available are enough to go from the genesis-block to the latest block. So they always hold the latest version of an instance, but not necessarilyĀ all versions. So it might take some F5 reloadings to get old data from a random node…

As it prints the version-number and the length of the data, I simply looked at the place where the length of the data all of a sudden decreased – this is where my addressbook got deleted!

17:06:48 -> 
Version 778 at block 100218 with length 2961

17:06:48 -> 
Version 777 at block 100214 with length 2959

17:06:48 -> 
Version 776 at block 100213 with length 4913

17:06:48 -> 
Version 775 at block 100211 with length 4913

So the last good version of my credential instance seems to be version 776.

Setting new data

This part is not for the faint of the heart. It overwrites the data on the blockchain, so if you remove for example all access delegations, nobody will be able to recover anything from your account. Which is very nice if you want to delete it, not so nice if you want to fix things.

Before I overwrote the data, I actually had a look at it if it made sense. The following code gets version 776 from my instance, the one with the bigger data, and prints out the addressbook. The addressbook is stored in theĀ Attribute of the credential underĀ 1-public/contactsBuf as an array of bytes:

// Get the old version of the credential instance
const contactInstance = await this.bcs.bc.getInstanceVersion(this.bcs.user.credStructBS.id, Long.fromNumber(776));
const credStruct = CredentialStruct.decode(contactInstance.statechange.value);
// Extract the addressbook and display it
const contactsBuf = credStruct.getAttribute("1-public", "contactsBuf");
this.log(contactsBuf);

That looked good – it was a long stream of bytes, which I hoped was my addressbook. To play it safe, I could’ve used the OL-demo underĀ Contacts and copy 64 hex-bytes at a time usingĀ Link Contact. But there were many contacts, so I double-checked the following and ran it:

this.bcs.user.executeTransactions((tx) => {
    this.bcs.user.credStructBS.credPublic.contacts.setInstanceSet(tx, new InstanceSet(contactsBuf));
})

This creates a new transaction and executes it. The dynacred-library allows for updating the structures by passing this transactionĀ tx variable to specific methods. Chaining multiple instructions is done by calling multiple methods in the callback of theĀ executeTransactions method. The transaction will be signed and sent to ByzCoin, and if all instructions are valid, the global state will be updated with the new data:

MY ADDRESSBOOK IS BACK!

Recovering an account

So, in fact this was great, as somebody just asked me to recover his account. With my addressbook back, I could search his account, and, as he still trusts me, click onĀ Recover. This is similar to adding a new device to the account, which creates an URL that can be used to link a browser to the account. So I sent this URL over email. Once clicked on the URL, it will connect to demo.c4dt.org/omniledger and store the private key in the browser. Then the person should be ready to use it. Or not, if there is a corporate firewall šŸ™