Revoking Documents
It's possible to revoke a signed document only if you fulfill certain prerequisites. Any future progress can be followed here.
Prerequisites:
- an
ethr
DID (if you've been following the above steps, you should have one already) - some kind of DID documents:
- a deployed
documentStore
, click here for how to do so. - before you wrap your document with the wrapper SDK, add a
revocation
block with these keys:
{
"$template": {
"name": "main",
"type": "EMBEDDED_RENDERER",
"url": "https://tutorial-renderer.openattestation.com"
},
"recipient": {
"name": "John Doe"
},
"issuers": [
{
....
"name": "Demo Issuer",
"revocation": {
"type": "REVOCATION_STORE",
"location": "<DEPLOYED_DOCUMENT_STORE_LOCATION>"
},
...
}
]
}
- note that the
<DEPLOYED_DOCUMENT_STORE_LOCATION>
is yourdocumentStore
location, it must be deployed on the blockchain (for now. Further implementations will relax this requirement so that DID documents will truly be gasless). - wrap your document, sign it and appending the signature to the document (follow the tutorial)
Revoking a document
- once you have achieved the prerequisites, you would have a document that could be revoked on a deployed
documentStore
. - how one does this is by simply invoking the command to revoke a document:
- CLI
- Code
tradetrust document-store revoke --address <DOCUMENT_STORE_ADDRESS> --hash <HASH_OF_DOCS> --network <NETWORK> --encrypted-wallet-path <PATH_OF_WALLET>
In the example above:
--address
is the document store address, for instance the one created with the Deploying Document Store guide.--hash
is the value oftargetHash
field of one of the previously wrapped documents (open one of the file, head to the bottom and check for thetargetHash
in thesignature
object.)
You will be prompted for the password that you used while creating the wallet. You will see a message after completion of the command:
✔ success Document/Document Batch with hash 0x1e0c5e93c04032ed6571b31c785b963f0a27776041f35bdcc98cd8dfe073adc0 has been revoked on 0xBBb55Bd1D709955241CAaCb327A765e2b6D69c8b
const unconnectedWallet = new Wallet("privateKey");
const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545"); // Local network
const wallet = unconnectedWallet.connect(provider);
const documentStore = DocumentStoreFactory.connect("0x63A223E025256790E88778a01f480eBA77731D04", wallet);
const tx = await documentStore.revoke("0x8dcf358a9436bca6654f565e3c5843d91c0052d3a2eff37bbd380038e8a1fa39");
const receipt = await tx.wait();
console.log(`Revoke Transaction: ${JSON.stringify(receipt)}`);
const isIssued = await documentStore.isRevoked("0x8dcf358a9436bca6654f565e3c5843d91c0052d3a2eff37bbd380038e8a1fa39");
console.log(`Has been Revoked: ${isIssued}`); // Has been Revoked: true
// Revoke Transaction:
{
"to": "0x63A223E025256790E88778a01f480eBA77731D04",
"from": "0xe0A71284EF59483795053266CB796B65E48B5124",
"contractAddress": null,
"transactionIndex": 0,
"gasUsed": { "type": "BigNumber", "hex": "0xbb6c" },
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000040000000000000000000000100000000400000000000000000000000000000000000000800000000000000000000000000000",
"blockHash": "0x7ba420b317c537731de1c70b9b1075213b40b6b69dcde48c592e1b3ab7926e95",
"transactionHash": "0xe15b2f8fda95ff29338722458be80fe14817019f565c82cd24115fda3bc36ae2",
"logs": [
{
"transactionIndex": 0,
"blockNumber": 4742644,
"transactionHash": "0xe15b2f8fda95ff29338722458be80fe14817019f565c82cd24115fda3bc36ae2",
"address": "0x63A223E025256790E88778a01f480eBA77731D04",
"topics": [
"0x7283b5ab9758f7fba773279e4fd50ea7b136bd1d8371dcae9c5ce529c55343d7",
"0x8dcf358a9436bca6654f565e3c5843d91c0052d3a2eff37bbd380038e8a1fa39"
],
"data": "0x",
"logIndex": 0,
"blockHash": "0x7ba420b317c537731de1c70b9b1075213b40b6b69dcde48c592e1b3ab7926e95"
}
],
"blockNumber": 4742644,
"confirmations": 1,
"cumulativeGasUsed": { "type": "BigNumber", "hex": "0xbb6c" },
"effectiveGasPrice": { "type": "BigNumber", "hex": "0x0184d5b7b1" },
"status": 1,
"type": 2,
"byzantium": true,
"events": [
{
"transactionIndex": 0,
"blockNumber": 4742644,
"transactionHash": "0xe15b2f8fda95ff29338722458be80fe14817019f565c82cd24115fda3bc36ae2",
"address": "0x63A223E025256790E88778a01f480eBA77731D04",
"topics": [
"0x7283b5ab9758f7fba773279e4fd50ea7b136bd1d8371dcae9c5ce529c55343d7",
"0x8dcf358a9436bca6654f565e3c5843d91c0052d3a2eff37bbd380038e8a1fa39"
],
"data": "0x",
"logIndex": 0,
"blockHash": "0x7ba420b317c537731de1c70b9b1075213b40b6b69dcde48c592e1b3ab7926e95",
"args": ["0x8dcf358a9436bca6654f565e3c5843d91c0052d3a2eff37bbd380038e8a1fa39"],
"event": "DocumentRevoked",
"eventSignature": "DocumentRevoked(bytes32)"
}
]
}
Alternate way to Revoke a document (OCSP)
Alternately, you can also revoke a document using your own Online certificate Status Protocol (OCSP) responder. Simply put, an OCSP responder would be a service that would respond with the revocation status of a certificate and the reason it was revoked.
Revocation type and location
You would require a DID document with
revocation.type
:OCSP_RESPONDER
revocation.locatioin
:https://ocsp-sandbox.openattestation.com
You should use your own OCSP responder if you have one deployed. Otherwise, you can demo this feature using the Open Attestation OCSP Responder
{
"$template": {
"name": "main",
"type": "EMBEDDED_RENDERER",
"url": "https://tutorial-renderer.openattestation.com"
},
"recipient": {
"name": "John Doe"
},
"issuers": [
{
....
"name": "Demo Issuer",
"revocation": {
"type": "OCSP_RESPONDER",
"location": "<OCSP_RESPONDER_URL>"
},
...
}
]
}
Revoking a document
Refer to this readme to learn how to add a document to the OA OCSP Responder.
Verifying the document
Head to dev.tradetrust.io and drag and drop the revoked document. An error will be displayed on the webpage.
The document has been revoked, thus, we do not display the content of the document on our document viewer.
Revoking multiple documents
If you open the previously wrapped documents side by side, you will notice:
- they have a different
targetHash
: it uniquely identifies any document - they have the same
merkleRoot
: it uniquely identifies any group of wrapped documents.
When you revoke a document you can use any of those hash, but the result will be different depending on the one used:
- when using the
targetHash
, only the document will be revoked. - when using the
merkleRoot
, all the documents wrapped together (in the same batch) will be revoked.
If you run again the command above, by using the merkleRoot
of the documents, then all documents will be revoked.
Misc questions:
Q: hey you mentioned that if I use DID documents, I would not need to pay for transactions, but following this flow, I would still have to pay for at least 1 transaction (deploying a documentStore
), what gives?
A: yes, you are right, for now this implementation will still need at least 1 transaction to the ethereum blockchain. We are working on this so please be patient and watch this space.
Q: this might be a weird question but I did not issue any documents from the deployed documentStore
, how am I able to revoke this document from said documentStore
when in the first place, I did not even issue anything?
A: long story short, the revocation mapping in the documentStore
is a separate mapping from the issued mapping.