did:cow, a proposal for an ID resolution method with most of the convenience of did:plc/did:web and the robustness of a public blockchain
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

make resolve just resolve, add describe to report status

+58 -21
+3 -1
README.md
··· 177 177 - `deactivateByHash(cowHash)` — permanently deactivate by pre-computed hash 178 178 179 179 **CLI tool (`cli/cow.py`):** 180 - - `resolve <did>` — resolve to current state and fetch wrapped DID document 180 + - `resolve <did>` — fetch the wrapped DID document 181 + - `describe <did>` — show on-chain state (controller, wrapped DID, registration status) 182 + - `initialize <did>` — register on-chain without making any updates (useful to take advantage of low-gas periods) 181 183 - `update-wrapped <did> <newWrappedDID>` — update the wrapped DID 182 184 - `update-controller <did> <newController>` — transfer control 183 185 - `deactivate <did>` — permanently deactivate
+55 -20
cli/cow.py
··· 168 168 169 169 @cli.command() 170 170 @click.argument("did") 171 - @click.option("--no-doc", is_flag=True, help="Skip fetching the wrapped DID document.") 172 - def resolve(did, no_doc): 173 - """Resolve a did:cow DID to its current state and wrapped DID document. 171 + def resolve(did): 172 + """Fetch the DID document for a did:cow DID. 174 173 175 174 \b 176 175 DID format: did:cow:<controller_address>:<method>:<id> ··· 180 179 w3 = _w3() 181 180 contract = _contract(w3) 182 181 182 + wrapped_did, _ = contract.functions.resolveCow( 183 + _controller_address(controller_hex), 184 + initial_wrapped, 185 + ).call() 186 + 187 + if wrapped_did == "": 188 + raise click.ClickException("DID is deactivated") 189 + 190 + url, doc = _resolve_did_doc(_strip_did_prefix(wrapped_did)) 191 + click.echo(f"resolved from: {url}") 192 + click.echo(json.dumps(doc, indent=2)) 193 + 194 + 195 + @cli.command() 196 + @click.argument("did") 197 + def describe(did): 198 + """Show the on-chain state of a did:cow DID without fetching the wrapped DID document.""" 199 + controller_hex, initial_wrapped = _parse_cow_did(did) 200 + w3 = _w3() 201 + contract = _contract(w3) 202 + 183 203 wrapped_did, controller = contract.functions.resolveCow( 184 204 _controller_address(controller_hex), 185 205 initial_wrapped, ··· 189 209 click.echo("status: deactivated") 190 210 return 191 211 192 - initial_full = f"did:{initial_wrapped}" 193 - on_chain = wrapped_did != initial_full or controller != _controller_address(controller_hex) 194 - if not on_chain: 195 - click.echo("status: not yet registered on-chain") 196 - click.echo(f"wrapped: {wrapped_did} (from DID)") 197 - click.echo(f"controller: {controller} (initial)") 198 - else: 199 - click.echo("status: active") 200 - click.echo(f"wrapped: {wrapped_did}") 201 - click.echo(f"controller: {controller}") 212 + cow_hash = contract.functions.calculateCowHash( 213 + _controller_address(controller_hex), 214 + initial_wrapped, 215 + ).call() 216 + registered = bytes(contract.functions.cows(cow_hash).call()[1]).decode() != "" 202 217 203 - current_wrapped = _strip_did_prefix(wrapped_did) 204 - 205 - if not no_doc: 206 - click.echo("") 207 - url, doc = _resolve_did_doc(current_wrapped) 208 - click.echo(f"resolved from: {url}") 209 - click.echo(json.dumps(doc, indent=2)) 218 + click.echo(f"status: {'active' if registered else 'not registered on-chain'}") 219 + click.echo(f"wrapped: {wrapped_did}") 220 + click.echo(f"controller: {controller}") 210 221 211 222 212 223 @cli.command("update-wrapped") ··· 260 271 261 272 _send(w3, account, tx) 262 273 click.echo(f"controller: {Web3.to_checksum_address(new_controller)}") 274 + 275 + 276 + @cli.command() 277 + @click.argument("did") 278 + def initialize(did): 279 + """Register a did:cow on-chain without making any updates. 280 + 281 + \b 282 + Useful for locking in registration during low-gas periods before any 283 + updates are needed. Has no effect if already registered. 284 + """ 285 + controller_hex, initial_wrapped = _parse_cow_did(did) 286 + 287 + w3 = _w3() 288 + contract = _contract(w3) 289 + account = _account(w3) 290 + 291 + tx = contract.functions.initializeCow( 292 + _controller_address(controller_hex), 293 + initial_wrapped, 294 + ).build_transaction({"from": account.address}) 295 + 296 + _send(w3, account, tx) 297 + click.echo("initialized.") 263 298 264 299 265 300 @cli.command()