README.md in sidetree-0.1.4 vs README.md in sidetree-0.1.5

- old
+ new

@@ -1,11 +1,10 @@ -# [WIP]Sidetree for Ruby +# Sidetree for Ruby [![Build Status](https://github.com/azuchi/sidetreerb/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/azuchi/sidetreerb/actions/workflows/main.yml) [![Gem Version](https://badge.fury.io/rb/sidetree.svg)](https://badge.fury.io/rb/sidetree) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) -Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sidetree`. To experiment with that code, run `bin/console` for an interactive prompt. +This is an experimental library that implements the [Sidetree protocol](https://identity.foundation/sidetree/spec/) in Ruby. +If you use this library, please test to see if it works properly with [reference implementation](https://github.com/decentralized-identity/sidetree). -TODO: Delete this and the text above, and describe your gem - ## Installation Add this line to your application's Gemfile: ```ruby @@ -20,10 +19,245 @@ $ gem install sidetree ## Usage -TODO: Write usage instructions here +### Environment + +Currently, this library support mainnet and testnet. +If you want to run with testnet, configure the network with the following code. + +```ruby +Sidetree::Params.network = Sidetree::Params::Network::TESTNET +``` +### Create new DID + +```ruby +# Generate recovery key +recovery_key = Sidetree::Key.generate + +# Generate update key +update_key = Sidetree::Key.generate + +# Generate signing key +signing_key = Sidetree::Key.generate(id: "signing-key") + +# Create DID Document from signing key +document = Sidetree::Model::Document.new(public_keys: [signing_key]) + +# Create DID +did = + Sidetree::DID.create( + document, + update_key, + recovery_key + ) +=> "did:sidetree:test:EiAw8oTzWzmPyTANALvzeHkCc6-uQ7XxnohqphrwC_jhNg:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJzaWduaW5nLWtleSIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJJQ3BuZXVJZ2ZqZW5UZzhhMmVCeEd1RkVjV1lwZkFTcDRXdHVmbmdGd3owIiwieSI6IlNPbUxzSzhIWlU0bmY5YWZCQmF0SlJUSjVWeGZSMlVRZ1hFVV8xTXVyTzgifSwicHVycG9zZXMiOltdLCJ0eXBlIjoiRWNkc2FTZWNwMjU2azFWZXJpZmljYXRpb25LZXkyMDE5In1dLCJzZXJ2aWNlcyI6W119fV0sInVwZGF0ZUNvbW1pdG1lbnQiOiJFaUExQ1l4NWE5NTlPRGRicThrMG1WUDJwZmVEY0RXaHd3TXhWamNDS2tZOXF3In0sInN1ZmZpeERhdGEiOnsiZGVsdGFIYXNoIjoiRWlDWklRdjlyeVVDR2dLbjMtSjNfTV9ZN0k1VTIyZlpldFRaSTFxSjZqdnVEQSIsInJlY292ZXJ5Q29tbWl0bWVudCI6IkVpQ2dPTGRPb0F5a3A4SzBrMlNwMmlzRUtNOFpmRnBVSWhVcnRLbUEydEcxcWcifX0" +``` + +### DID operation + +#### Create Operation + +```ruby +# Generate Create Operation +create_op = did.create_op + +# Generate Chunk File from create operation +chunk_file = Sidetree::Model::ChunkFile.create_from_ops(create_ops: [create_op]) + +# Write chunk file to IPFS +# Initialize IPFS client(If the parameter is omitted, the default is to access http://localhost:5001/api/v0.) +ipfs = Sidetree::CAS::IPFS.new + +chunk_file_uri = ipfs.write(chunk_file.to_compress) + +# Generate Provisional Index File and write to IPFS +provisional_index_file = Sidetree::Model::ProvisionalIndexFile.new(chunks: [Sidetree::Model::Chunk.new(chunk_file_uri)]) +provisional_index_file_uri = ipfs.write(provisional_index_file.to_compress) + +# Generate Core Index File and write to IPFS +core_index_file = Sidetree::Model::CoreIndexFile.new( + create_ops: [create_op], + provisional_index_file_uri: provisional_index_file_uri +) +core_index_file_uri = ipfs.write(core_index_file.to_compress) + +# Generate Anchor String to anchoring to Bitcoin +anchor_str = Sidetree::Util::AnchoredDataSerializer.serialize(1, core_index_file_uri) +``` + +#### Update Operation + +```ruby +# DID suffix to be updated +did_suffix = "EiBRrmEha_Q30GieEwLB-XM8CZd_b49dQ7znhaBxfAHTsQ" + +# Current update key +update_key = Sidetree::Key.new(private_key: <private key>) + +# Generate new signing key +new_signing_key = Sidetree::Key.generate(id: "signing-key") + +# Create replace DID Document +document = Sidetree::Model::Document.new(public_keys: [new_signing_key]) + +# Generate next update key +next_update_key = Sidetree::Key.generate + +# Generate update delta object +delta = + Sidetree::Model::Delta.new( + [document.to_replace_patch], + next_update_key.to_commitment + ) + +# Generate jws and sign with update key +claim = { updateKey: update_key.to_jwk.normalize, deltaHash: delta.to_hash } +jws = Sidetree::Util::JWS.sign(claim, update_key) + +# Generate Provisional Proof File and write to IPFS +provisional_proof = Sidetree::Model::ProvisionalProofFile.new([jws]) +provisional_proof_uri = ipfs.write(provisional_proof.to_compress) + +# Create update operation +update_op = + Sidetree::OP::Update.new(did_suffix, delta, jws, update_key.to_reveal_value) + +# Generate Chunk File and write to IPFS +chunk_file = + Sidetree::Model::ChunkFile.create_from_ops(update_ops: [update_op]) +chunk_file_uri = ipfs.write(chunk_file.to_compress) + +# Generate Provisional Index File and write to IPFS +provisional_index_file = + Sidetree::Model::ProvisionalIndexFile.new( + proof_file_uri: provisional_proof_uri, + chunks: [Sidetree::Model::Chunk.new(chunk_file_uri)], + operations: [update_op] + ) +provisional_index_file_uri = ipfs.write(provisional_index_file.to_compress) + +# Generate Core Index File and write to IPFS +core_index_file = + Sidetree::Model::CoreIndexFile.new( + provisional_index_file_uri: provisional_index_file_uri + ) +core_index_file_uri = ipfs.write(core_index_file.to_compress) + +anchor_str = + Sidetree::Util::AnchoredDataSerializer.serialize(1, core_index_file_uri) +``` + +#### Recover Operation + +```ruby +did_suffix = "EiBRrmEha_Q30GieEwLB-XM8CZd_b49dQ7znhaBxfAHTsQ" + +# Current recovery key +recovery_key = Sidetree::Key.new(private_key: <private key>) + +# Generate new recovery key +new_recovery_key = Sidetree::Key.generate + +# Generate new update key +new_update_key = Sidetree::Key.generate + +# Generate new signing key +new_signing_key = Sidetree::Key.generate(id: "signing-key") + +# Generate replace DID Document +document = Sidetree::Model::Document.new(public_keys: [new_signing_key]) +delta = + Sidetree::Model::Delta.new( + [document.to_replace_patch], + new_update_key.to_commitment + ) + +# Generate jws and sign with recovery key +claim = { + recoveryKey: recovery_key.to_jwk.normalize, + recoveryCommitment: new_recovery_key.to_commitment, + deltaHash: delta.to_hash +} +jws = Sidetree::Util::JWS.sign(claim, recovery_key) + +# Generate Core Proof File from jws +core_proof_file = Sidetree::Model::CoreProofFile.new(recover_proofs: [jws]) +core_proof_file_uri = ipfs.write(core_proof_file.to_compress) + +# Create recover operation +recover_op = + Sidetree::OP::Recover.new( + did_suffix, + delta, + jws, + recovery_key.to_reveal_value + ) + +# Generate Chunk File and write to IPFS +chunk_file = + Sidetree::Model::ChunkFile.create_from_ops(recover_ops: [recover_op]) +chunk_file_uri = ipfs.write(chunk_file.to_compress) + +# Generate Provisional Index File and write to IPFS +provisional_index_file = + Sidetree::Model::ProvisionalIndexFile.new( + chunks: [Sidetree::Model::Chunk.new(chunk_file_uri)] + ) +provisional_index_file_uri = ipfs.write(provisional_index_file.to_compress) + +# Generate Core Index File and write to IPFS +core_index_file = + Sidetree::Model::CoreIndexFile.new( + provisional_index_file_uri: provisional_index_file_uri, + core_proof_file_uri: core_proof_file_uri, + recover_ops: [recover_op] + ) +core_index_file_uri = ipfs.write(core_index_file.to_compress) + +anchor_str = + Sidetree::Util::AnchoredDataSerializer.serialize(1, core_index_file_uri) +``` + +#### Deactivate operation + +```ruby +# Current recovery key +recovery_key = Sidetree::Key.new(private_key: <private key>) + +# Generate jws and sign with recovery key +claim = { + didSuffix: did_suffix, + recoveryKey: recovery_key.to_jwk.normalize +} +jws = Sidetree::Util::JWS.sign(claim, recovery_key) + +# Generate Core Proof File and write to IPFS +core_proof_file = Sidetree::Model::CoreProofFile.new(deactivate_proofs: [jws]) +core_proof_file_uri = ipfs.write(core_proof_file.to_compress) + +# Create Deactivate Operation +deactivate_op = + Sidetree::OP::Deactivate.new( + did_suffix, + jws, + recovery_key.to_reveal_value + ) + +# Generate Core Index File and write to IPFS +core_index_file = + Sidetree::Model::CoreIndexFile.new( + core_proof_file_uri: core_proof_file_uri, + deactivate_ops: [deactivate_op] + ) +core_index_file_uri = ipfs.write(core_index_file.to_compress) + +anchor_str = + Sidetree::Util::AnchoredDataSerializer.serialize(1, core_index_file_uri) +``` + +The pseudocode above all anchor a single operation, but you can be combined into a batch(i.e. to single anchor string). ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.