Will Abramson
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # **did:btc1** Specification # SPEC NO LONGER MAINTAINED HERE ## Moved to https://gl1.dcdpr.com/btcr ## 1. Introduction **did:btc1** is the secure, reliable bitcoin DID method. It uses bitcoin as a Verifiable Data Registry to store canonical status for a new type of DID. **did:btc1** is designed to be secure, flexible and resilient. It supports offline creation, aggregate and singleton DID updates, all without late publishing and without requiring public disclosure of DID documents. * Offline creation allows creating DIDs without interacting with the bitcoin blockchain. * Aggregated updates allow an arbitrary number of DID document updates to be combined by any agregator and posted to Bitcoin in a single transaction. * Directed updates means that resolving parties need only process transactions likely to contain updates for those DIDs of intereset. * Late publishing is avoided by ensuring 100% valid coverage of the entire update history without gaps or ambiguity. * Public disclosure of DID documents can be avoided by using a "sidecar" delivery of the necessary DID history along with the DID itself. * Beacons specified in each DID document point to sources for subsequent updates, allowing DID controllers to provide any number of mutually authoritative update sources for resiliency. ### Offline Creation **did:btc1** supports offline creation in two modes: * deterministically from a key pair and * from an arbitrary initiating DID document. Deterministic creation means that the DID itself encodes a cryptographic seed that can be used to automatically generate the entire initial DID document. This enables DID creation at computation cost, requiring neither additional network activity nor additional information to resolve the initial DID document. Initiating DID document creation means that the DID itself encodes a content identifier (an IPFS compatible CID) of the initiating DID document. Resolvers either retrieve that document from IPFS or have it provided directly in a technique we refer to as sidecar resolution because the secured update history must be separatly provided by the DID controller along with the DID, much as a sidecar on a motorcycle brings along a second passenger. Once created, a **did:btc1**'s DID document can be updated by posting a signed update bundle to a "beacon" specified in the current DID document. ### Beacons Beacons provide secured, authoritative sources for DID document updates. They enable resilient, verifiable, and aggregatable updates. Specified in every DID document, Beacons tell resolving parties where to check next for future updates. **All** Beacons are addresses on Bitcoin. Resolvers watch those addresses for updates to DIDs of interest. Spends from those addresses indicate an update, with the appropriate details for how to get the update bundle for processing. These spends are Beacon Signals which may contain updates for the DID in question and which are guaranteed to be approved by the DID controller whether or not their particular DID has an update. Because each DID document specifies which Beacons a resolver should check, resolvers need only process the transactions that are valid spends from an address the DID controller signs:the Beacon's Bitcoin address. This approach minimizes the computational and network overhead for resolving a DID to just those updates from explicitly listed Beacons. Every update to the DID document is made by a signed update published by a spend from one or more Beacons. The signed update includes a content reference to the prior version and an explicit version ID, so that the entire chain of updates can be verified by any resolver. Duplicate identical updates posted to different Beacons is fine, but if different signed updates to the same version are ever seen, resolvers MUST declare the DID invalid. This prevents late publishing. All updates are gauranteed to be signed by the controller of the DID. ### Singleton and Aggregate Beacons This specification defines both singleton and aggregate Beacons. Singletons enable a single DID controller to independently post an update for a single DID. Aggregate Beacons allow arbitrary numbers of updates to be recorded in a single Bitcoin transaction. This includes both updates to multiple DIDs by the same controller as well as updates from multiple controllers on a myriad of DIDs, processed through an untrusted aggregator. The worst an aggregator can do is refuse to accept a controller's DID update, in which case the controller can simply using another Beacon, including the singleton expected in every DID document. Becase every update is signed by just that DID's controller, all updates are authenticatable. Each aggregate Beacon address is a multi-sig (taproot) n-of-n puzzle that must be signed by the entire cohort of participating DIDs, guaranteeing that every update bundle is approved by every participant in that cohort. When an update bundle lacks an update to a particular DID in a cohort (because other controllers are updating), that DID's controller can verify the bundle is correct (no update for their DIDs) so we know without ambiguity when a Beacon Signal DOES NOT contain an update for a given DID. ### Complete History & Sidecars In **did:btc1**, all resolvers MUST check all Beacons across time and verify a single unique history of updates. Any missing updates or incompatible histories render the DID invalid. For a DID controller comfortable with acting publicly, DID document updates can readily be posted to content-based storage networks, like IPFS, for retrieval by anyone. However, for situations requiring more discretion, DID controllers may choose to simply publish the fact of an update without publicly distributing the update itself. In that case, resolvers must find the updates on their own, presumably by contacting the DID controller. In this "sidecar" pattern, controllers provide not just the DID, but also any update bundles that cannot be found publicly. Since Beacon singletons do not rely on collaborators the way aggregate Beacons do, making sure every DID document has at least one singleton Beacon guarantees updateability even if all aggregators fail. ## 2. Syntax > [color=blue] **Discuss**: > * What is the ABNF for a CID? > * How do we support multiple/arbitrary CID types such that the initial DID document could be stored on any Content Addressable Storage (CAS) OR could be held and produced by the DID controller in a sidecar fashion. > > Note: this needs to be defined for the sidecar offline DID and also the type of CIDs broadcast in beacon signals > [name=joe] YOU COULD PROBABLY CONSTRUCT AN abnf WITH THE MULTIBASE AND MULTICODEC PREFIXES AND THE MULTIBASE VERSION. See https://proto.school/anatomy-of-a-cid/02 > > The a **did:btc1** DID consists of a `**did:btc1**` prefix, followed by an optional `version` number, an optional bitcoin `network` identifier and finally a `method-id`value. The `method-id` is either a base58-btc encoded `key-value` representing a secp256k1 public key, or a content identifier (CID) for the DID documents initial state. If a `version` is not specified, then it is assumed to be version 1. If a `network` is not specified then it is assumed to be mainnet. Note: the `version` is a syntax version, not a spec version. Version is always first so that its ordering within the syntax is invariant into the future. The ABNF for a **did:btc1** DID follows: ```abnf did-btc = "**did:btc1**:" [ version ":" ] [ network ":" ] method-id method-id = key-value / hash-value hash-value = TODO key-value = *base58btcchar version = 1*DIGIT network = "mainnet" / "signet" / "testnet" / "regnet" base58btcchar = "1" / "2" / ... / "9" / "A" / "B" / ... / "H" / "J" / "K" / ... / "N" / "P" / "Q" / ... / "Z" / "a" / "b" / ... / "k" / "m" / "n" / ... / "z" ``` > [color=orange] **TODO**: Incorporate the DID URL into the ABNF. > [color=orange] **TODO**: Create a diagram to represent the ABNF and the variants it supports. Generic ABNF notation can be found [here](https://www.tech-invite.com/fo-abnf/tinv-fo-abnf.html). ### 2.1 Examples All the four following DIDs are equivalant. * **did:btc1**:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm - MOST COMMON * **did:btc1**:1:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm * **did:btc1**:mainnet:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm * **did:btc1**:1:mainnet:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm # 3. Operations ## 3.1 Create > [color=red] **Decision Point:** Does create support both sidecar and deterministic approaches to DID creation? > 1. Yes [Decision] > 2. No, only determinstic ### 3.1.1 Deterministic Creation 1. Optionally select a `version` for the DID. Defaults to 1. 2. Select a bitcoin `network`. Defaults to `mainnet`. 3. Generate a secp256k1 key pair ``` KeyGen() -> (Pk, Sk) ``` >[name=Will] Abramson Should we add step around storing Sk? Or is this out of scope 4. Encode the public key using the base58-btc encoding ``` base58btc(Pk) -> Encoded_Pk ``` 5. Construct and return the DID following the ABNF (Sec 2), with the `key-value` set to the Encoded_Pk. If `version` is not 1, then it MUST be included in the DID. If `network` is not mainnet, then it MUST be included in the DID. ``` return **did:btc1**:<version>:<network>:<Encoded_Pk> ``` 4. To expand this DID to its initial DID document, follow the read steps defined in [Section 3.2](#did_resolution) ### 3.1.2 Offline DID document (Sidecar) It is possible to create a **did:btc1** from some initiating arbitrary DID document. This allows for more complex DID documents from the start, including the ability to have Service Endpoints and Beacons that support aggregation. 1. Optionally select a `version`, it defaults to `1`. 2. Select a btc `network` for the DID, it defaults to `mainnet`. 3. Create an arbitrary partial DID document, without the `id` field. The DID document SHOULD include: - A verificationMethod - At least one SingleUpdateBTCBeacon service for an address on the specified bitcoin `network` under the control of the DID controller > [color=blue] **Discuss**: Does it even matter if beacons are on the same network as the DID itself? I think yes. 4. Generate a `cid` (content identifier) for the partial DID document. > [color=blue] **Discuss**: What is the algorithm here? Is it up to the DID controller to select. There are many different types of CID. Typically the CID identifies the hash and version used to generate itself. 5. Construct DID as follows. If `version` is not 1, then it MUST be included in the DID. If `network` is not mainnet, then it MUST be included in the DID. ``` did = **did:btc1**:<version>:<network>:<cid> ``` 6. The initial DID document is the partial DID document with the `id` field set to the `did`. > [color=blue]**Discuss**: Do we also need to update all verificationMethod controller fields to be this DID? > [name=joe](yes.) ## 3.2 Read <div id="did_resolution"/> The read method, takes a **did:btc1** `identifier` and returns the latest DID document at the time of resolution. To do so, resolution first retrieves/generates the initial DID document for the identifier and subsequently processes all signals from beacons included in that DID document. Applying updates to the DID document as appropriate. 1. Initialize a document variable as an empty object 2. Using a colon (`:`) as the delimiter, split the `identifier` into its components: a *scheme*, a *method*, a *version*, a *network*, and a *method-id*. If there are only three components, set the *version* to `1` and *network* to `mainnet` use the last value as the *method-id*. If there are four components, check if the second component can be cast to an integer. If so, set *version* to this value and *network* to `mainnet`. Otherwise, set the *network* to the component value and *version* to `1`. 3. Check the validity of the identifier. The *scheme* MUST be the value `did`. The *method* MUST be the value `btc`. The *version* MUST be convertible to a positive integer value. If any of these requirements fail a `InvalidDID` error MUST be raised. 4. Test if `method-id` is a base58 encoded Secp256k1 public key. - Set `rawKeyBytes` to the base58 decoded `method-id`. - Check the length of `rawKeyBytes` is 33 - Parse `rawKeyBytes` as a sec encoding of a Sec256k1 public key - If a valid key run 3.2.1 Deterministic Resolution with `identifier`, `rawKeyBytes` and `network` - Else run 3.2.2 Sidecar Resolution ## 3.2.1 Deterministic Resolution 1. Set `document.id` to the identifier. 2. Initialize a contextArray to empty array - Append the DID core context (https://www.w3.org/ns/did/v1) - Append the JWS context (https://w3id.org/security/suites/jws-2020/v1) - Append a **did:btc1** context - Set `document['@context]' to contextArray` > [color=orange] **TODO**: Define a **did:btc1** context 3. Create initial verification method 3.1. Initialize `verificationMethod` to an empty object 3.2. Set`verificationMethod.id` to #initialKey 3.3. Set `verificationMethod.type` to "JsonWebKey" 3.4. Set `verificationMethod.controller` to `identifier` 3.5. Set `x` as the hex encoded `rawKeyBytes`. 3.6. Set `verificationMethod.publicKeyJwk` to: ```json { "kty": "EC", "crv": "secp256k1", "x": x } ``` > [color=red] **Decision Point:** How should we represent cryptographic keys when deterministically generating initial DID documents? > 1. Use Json Web Key [Selected] > 2. Use Multibase/Multikey > 3. Allow the resolver to define this by passing in an options configuration (see did:key) 4. Set `document.verificationMethod` to `verificationMethod` 5. Initialize the authentication, assertionMethod, capabilityInvocation, and the capabilityDelegation properties in document to an array where the first item is the `verificationMethod.id`. 6. Initialize the `document.services` property in `document` to the result of passing the `key-value`, `network` and `identifier` to the [3.2.3 Deterministicly Generate Beacon Services](#deterministically_generate_beacons) Algorithm. 7. Run through the [3.2.4 Process Beacon Updates](#process_beacon_updates) algorithm passing in the `document.services` property. ### 3.2.2 Sidecar Resolution Sidecar resolution requires additional sidecar data, specifically the initiating DID document `document`, to be passed in the resolution request. How the resolver gets this data is out of scope, but it is likely provided by the controller of the DID being resolved. 1. Check `document.id` equals id of DID being resolved. If not MUST raise a resolution error. 2. Create a partial DID document object, by copying the initial `document` and removing this `id` field. 4. Hash the partial DID document. 5. Check the hash equals the `method-id`. If not MUST raise a resolution error. 6. Run through the [3.2.4 Process Beacon Updates](#process_beacon_updates) algorithm passing in the `document.services` property. > [color=blue] **Discuss**: Do we need canonicalizion here? <div id="deterministically_generate_beacons"/> ### 3.2.3 Deterministicly Generate Beacon Services This algorithm deterministically generates three beacons from the single `key-value` used to generate the deterministic **did:btc1**. One beacon for each of the following three bitcoin address types for the bitcoin `network` specified by the DID: Pay to public key hash (p2pkh), pay to witness public key hash (p2wpkh) and pay to taproot (p2tr). Spends from these three addresses can be produced only through signatures from the `key-value`'s associated private key. Each beacon is of the type SingleUpdateBTCBeacon. > [color=red] **Decision Point:** Which bitcoin address types should be used to deterministially generate initial beacons from a keyValue? > 1. p2pkh > 2. p2wpkh > 3. p2tr > 4. Generate a beacon for each [**CHOICE**] 1. Initialize a `services` variable to an empty array. 2. Decode the `key-value` to get a `rawPublicKeyBytes` value. 3. Initialize a `p2pkhBeacon` variable to the result of passing `network`, `rawPublicKeyBytes`, `network` and `p2pkh` to 3.2.3.1 Deterministically Generate Beacon Service. 4. Push `p2pkhBeacon` to `services 5. Initialize a `p2wpkhBeacon` variable to the result of passing `network`,`rawPublicKeyBytes` and `p2wpkh` to 3.2.3.1 Deterministically Generate Beacon Service. 6. Push `p2wpkhBeacon` to `services` 7. Initialize a `p2trBeacon` variable to the result of passing `network`, `rawPublicKeyBytes` and `p2tr` to 3.2.3.1 Deterministically Generate Beacon Service. 8. Push `p2trBeacon` to `services` 9. Return the `services` array. #### 3.2.3.1 Deterministically Generate Beacon Service > [color=red] What should the default CAS type used in deterministic generation be? > 1. IPFS > 2. ...? Generates a beacon service from a `rawPublicKeyBytes`, a btc `network` and a `addressType`. 1. Initialize a `beacon` variable to an empty object. 2. Initialize an `address` variable to the result of generating the bitcoin address specified by the `addressType` from the `rawPublicKeyBytes` value. 3. Initialize an `addressURI` variable to the result of converting `address` to a URI as per **[BIP21](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki)** 4. Set `beacon.type` to SingleUpdateBTCBeacon. 7. Set the `beacon.id` value by concatinating the `identifier`, a `#`, `key-value` and `1`. > [name=Will Abramson Maybe the id should be identifier#address?] 5. Set `beacon.serviceEndpoint` to `addressURI` 6. Return `beacon` <div id="process_beacon_updates"/> ### 3.2.4 Process Beacon Updates Algorithm This algorithm takes in a DID document, identifies its current active beacons and then fetches all signals from each beacon. Beacon signals are bitcoin transactions published by a bitcoin address identified by beacon services in the DID document being resolved. These signals are then aggregated and ordered using the transaction's inclusion time within the bitcoin network. Once complete, signals are processed in order. Processing signals retrieves DID update data, containing a set of deltas that mutate the DID document and the canonical order that this mutation should be applied to the DID document. Updates MUST be applied in the order they are defined and updates with the same order MUST be the equivalent. As each signal is processed, the set of aggregated beacon signals MUST be recalculated if the beacon services identified in the DID document changes. Once all signals from all active beacons have been processed the latest DID document is returned. 1. Initialize a `orderedSignals` variable to an empty array. 2. Initialize a `latestDocument` variable to `document`. 3. Initialize `activeBeaconIDs` to an empty array. 4. Initialize `latestUpdateOrder` to 0 5. Initialize `processedUpdates` and `pendingUpdates` to empty arrays. 6. Identify all beacons in the `document.service` array and store in a `beaconServices` array. 7. For each `beaconService` in `beaconServices`: - If `beaconService.id` NOT IN `activeBeaconIDs`: - Set `beaconSignals` to the result of passing `beaconService` into the 3.2.4.1 Fetch Beacon Signals algorithm. - Push `beaconSignals` to the `orderedSignals` array. - Push `beaconService.id` to `activeBeaconIDs` 8. If `activeBeaconIDs.length !== beaconServices.length`: - Identify beaconIds in `activeBeaconIDs` and NOT in the `beaconServices` array. Store in `removedBeaconIDs`. - Remove all signals from the `orderedSignals` array with a `signal.beaconId` value in the `removedBeaconIDs` array. - Remove `removedBeaconIDs` from the `activeBeaconIDs` array. - Set `removedBeaconIDs` to an empty array - Expect the length of `activeBeaconIDs` to equal the length of `beaconServices` 9. If `orderedSignals` is empty, return `latestDocument`. 10. Order the `orderedSignals` array using the `signal.blockTime` property on each `signal` element in the array. 11. For each `signal` in `orderedSignals`: - Set `type` to `signal.beaconType` - Set `didUpdateInvocation` to the result of passing `signal.tx` to the Process Beacon Signal algorithm defined by the corresponding Beacon `type`. See [Section 4 Beacons](#beacons). - Verify the `didUpdateInvocation`, if invalid raise InvalidUpdateInvocation error. - If `didUpdateInvocation.order` <= `latestUpdateOrder`: - Set `processedUpdate` to the update with order `didUpdateInvocation.order` in `processedUpdates`. - Check hash of `processedUpdate` is equal to `didUpdateInvocation`. If not, then MUST raise a `latePublish` error. - Else if `didUpdateInvocation.order` == `latestUpdateOrder + 1`: - Apply the JSON0 transformation `didUpdateInvocation.updateTransformation` to the `latestDocument` - Set `latestUpdateOrder` to `didUpdateInvocation.order` - Push `didUpdateData` to `processedUpdates` - If pendingUpdates contains an update with order equal to `latestUpdateOrder + 1`. Process update by returning to step 11 - Else: - Push `didUpdateInvocation` to `pendingUpdates` if update with that order does not exist in pendingUpdates. If it does, check hashes are the same or throw error. - Remove `signal` from the `orderedSignals` array - Return to step 6. > [name=Will Abramson The idea with this algorithm is that you would keep processing beacon signals in the aggregated order they were submitted to the bitcoin network until no signals were left. When orderedSignals array is empty, you return the latestDocument.] ```mermaid sequenceDiagram autonumber Note left of Resolver: Alorithm takes in a DID document<br/> and the name of a bitcoin network. Resolver->>Resolver:Initialize orderedSignals to empty array Resolver->>Resolver:Initialize latestDocument to document Resolver->>Resolver:Initialize processedUpdates and pending to an empty array Resolver->>Resolver:Initialize latestUpdateOrder to 0 Resolver->>Resolver:Find all beacon services in latestDocument.services and store in a beaconServices array Resolver->>Resolver:For beaconService in beaconServices Resolver->>Bitcoin network:Fetch beacon signals Bitcoin network->>Resolver:signals Resolver->>Resolver:Push signals to orderedSignals array Note over Resolver: Ordering by blocktime not strictly necessary? <br/>But better for efficiency Resolver->>Resolver:Order orderedSignals on blockTime Resolver->>Resolver:For signal in orderedSignals Note over Resolver: Process beacon signal is defined<br/>by a separate sequence diagram for each beacon type. Resolver->>Resolver:Process beacon signal according to beacon type to retrieve didUpdateInvocation Resolver->>Resolver:Verify didUpdateInvocation alt didUpdateInvocation.order <= latestUpdateOrder Resolver->>Resolver:Set processedUpdate in processedUpdates with order equal to didUpdateInvocation Resolver->>Resolver:If hash of processedUpdate does NOT Equal hash of didUpdateInvocation raise LatePublish error else didUpdateInvocation.order == latestUpdateOrder + 1 Resolver->>Resolver:Apply didUpdateInvocation.update to the latestDocument Resolver->>Resolver:Set latestUpdateOrder to didUpdateInvocation.order Resolver->>Resolver:push didUpdateInvocation to processedUpdates Note over Resolver: Attempting to represent a loop here. Resolver->>Resolver:If pendingUpdates contains an update with order latestUpdateOrder + 1. Process from step 16. else didUpdateOrder > latestUpdateOrder + 1 Resolver->>Resolver:Push didUpdateInvocation to pendingUpdates end Resolver->>Resolver:Remove signal from orderedSignals ``` #### 3.2.4.1 Fetch Beacon Signals Algorithm This algorithm takes in a bitcoin `network` from the `identifier` and single `beaconService` as defined in a DID document. It then fetches all associated bitcoin transactions and returns an array of beaconSignals. Each signal in the array contains the beaconId, the bitcoin transaction, the beacon type and the blocktime for the transaction. > [color=blue] **Discuss** This only considers Beacon Signals whose service endpoints are Bitcoin address URLs. We may want to add some more steps here about checking the type. The Fetch Beacon Signals Algorithm could be another function defined by the beacon? > [color=red] **Decision Point:** Does/can **did:btc1** support beacons that are not Bitcoin addresses? > - No, not initially. Maybe through extension? > [color=blue] **Discuss**: The challenge with adding new beacon types will be that all resolvers MUST support all the beacon types. Or there could be another potential route for late publishing 1. Initialize a `beaconSignals` variable to an empty array. 2. Set `beaconAddressURI` to `beaconService.serviceEndpoint` 3. Set `beaconAddress` to the conversion of `beaconAddressURI` to a bitcoin address following BIP21. 4. Set `spendTxs` to the spends on the Bitcoin blockchain `network` from the `beaconAddress`. 5. For each `tx` in `spendTx`: - Find the `blockTime` the `tx` was included in the ledger > [color=blue] **Discuss:** Is ordering by blocktime worthwhile? - Initialize a `beaconSignal` variable to the value: ```json { "beaconId": beaconService.id, "beaconType": beaconService.type, "blockTime": blockTime, "tx": tx } ``` - Push `beaconSignal` to the `beaconSignals` array 6. Return `beaconSignals` ```mermaid sequenceDiagram autonumber Note left of Resolver:Inputs(beaconService, network) Note left of Resolver: Algorithm called from<br/>Process Beacon Updates Resolver->>Resolver:Initialize beaconSignals to an empty array Resolver->>Resolver:Set beaconAddressURI to beaconService.serviceEndpoint Resolver->>Resolver:Set beaconAddress to the BIP21 conversion of beaconAddressURI Resolver->>Bitcoin network:Fetch spendTxs from network for beaconAddress Bitcoin network->>Resolver:spendTxs Resolver->>Resolver:For each tx in spendTx Resolver->>Resolver:Find the blockTime the tx was included in the network Resolver->>Resolver:Initialize a beaconSignal json object. Including blockTime, beaconId, beaconType and tx Resolver->>Resolver:Push beaconSignal to beaconSignals array Note right of Resolver: Return beaconSignals ``` ## 3.3 Update An update is an invoked capability, signed by the key that has the authority to make the update as specified in previous DID document. Any key that is identified in the `document.capabilityInvocation` array. 1. Construct a `didUpdateDeltas` object containing the intended mutations to the DID document > [color=orange] **TODO** Specify DID Update Deltas Json. > [color=blue] **Discuss**: If we are using JSON0 to support arbitrary JSON mutations to a DID document how do we handle JSONLD conformance with the contexts? 2. Construct a `didUpdateInvocation` object. > [color=blue] **Disucss**: Capability invocations for updates needs further refining. 3. Set `didUpdateInvocation.deltas` to `didUpdateDeltas`. 4. Set `didUpdateInvocation.order` to the order of the update. (Previous order plus one) > [color=blue] **Discuss**: Another name for order? This number identifies the canonical sequence of updates preventing late publishing. Or in fact should this be the hash of the previous DID document? 5. Invoke the `didUpdateInvocation` by creating a valid `proof` attribute. Proof should be created through a signature over the invocation using keys defined in the previous didDocument capabilityInvocation field. > [color=orange] **TODO**: Need more detail here. This is Zcap stuff. 6. Identify a beacon(s) from the set of beacons in the DID document being updated 7. Pass the `didUpdateInvocation` and `beacon` to the Publish DID Update algorithm defined for the type of beacon selected. (See [Section 4. Beacons](#beacons)) ```mermaid sequenceDiagram autonumber DID Controller->>Update Service:Specify update deltas Update Service->>Update Service:Create didUpdateDeltas Update Service->>Update Service:Create didUpdateInvocation Update Service->>Update Service:Set didUpdateInvocation.deltas to didUpdateDeltas Update Service->>Update Service:Set didUpdateInvocation.order to the next number in the update sequence Update Service->>Update Service:Sign (invoke?) didUpdateCapability Update Service->>Update Service:Identify beacons in latest DID document Update Service->>DID Controller:Select beacon(s) DID Controller->>Update Service:beacons Update Service->>Update Service:For beacon in beacons Update Service->>Update Service:Publish DID Update Note right of Update Service: Publish DID Update is an algorithm<br/> defined by each beacon type separately. ``` ## 3.4 Deactivate > [color=blue] **Discuss**: How do we want the deactivate operation to work. The deactivate operation is a didUpdateInvocation where the deltas value is empty. <div id="beacons"/> # 4. Beacons > [name=Will Abramson What are the beacon types we intend to support/define in the spec. Or would infact they all be defined in there own spec, we just talk about the things a beacon needs to satisfy?] > [color=red] **Decision Point:** What beacon types does the spec support? > > **Decision Point:** Are beacons only onchain on the bitcoin ledger? > Initially, beacons are only ledger based. > > **Decision Point:** Is beacon type an extension point, potentially opening up a surface for website based beacons etc? Beacons are the mechanism by which a DID controller publishes updates to their DID document. The current beacons of a DID document are specified in the documents `services` property. By updating the DID document, a DID controller can change the set of beacons they can use to broadcast updates to their document over time. Resolution of a DID MUST take into account signals from all beacons identified in the latest DID document and process them in order determined by Bitcoin. **did:btc1** supports different beacon types, defining different approaches for publishing and verifying updates to a DID document. This is an extendable mechanism, such that in the future new beacon types could be added. It would be up to the resolver to determine if the beacon type is a mechanism they support and are willing to trust. If they are unable to support a beacon type and a DID they are resolving uses that type then the DID MUST be treated as invalid. All resolvers of **did:btc1** DIDs MUST support the core beacon types defined in this specification. > [color=red] **Decision Point:** What are the core/required beacon types of the **did:btc1** specification? > - SingleUpdate > - CIDAggregated > - SMTAggregated > - Other? Each beacon type MUST define: 1. How the beacon is established and added as a service to a DID document 2. How a DID controller submits a DID update to a beacon 3. How a resolver processes a beacon signal, identifying the DIDUpdateData for a specific DID ## 4.1 SingleUpdateBTCBeacon > [name=Will Abramson We should review beacon type names] > [color=red] **Decision Point:** What Content Addressable Storage (CAS) is used for this beacon? > **Answer:** Beacon services include an optional casType value. This defines the CAS to use. ### 4.1.1 Establish Beacon A SingleUpdateBTCBeacon, is a beacon that can be used to publish a single update to a single DID document. The serviceEndpoint for this beacon type is a bitcoin address represented as a URI following the [BIP21 scheme](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki). It is RECOMMENDED, that this bitcoin address is under the sole control of the DID controller. The algorithm is as follows: 1. Generate a secp256k1 keypair 2. Use the public key to generate a bitcoin address. p2pkh, p2wpkh, p2tr or some other custom bitcoin address. - It is possible to use an existing bitcoin address - Before the beacon can be used to publish an update it must be funded - The bitcoin address SHOULD be spendable by the DID controller 4. Set `beaconUri` to the URI for the address following BIP21 5. Initialize `beaconService` to: ```json { "id": "someid", //What should this be. Is the arbitrary? "type": "SingleUpdateBTCBeacon" "serviceEndpoint": beaconUri "casType": "IPFS" // Optional hint at the CAS storage used } ``` 6. Add `beaconService` to the DID document through an update following the algorithm defined in 3.3. Update ### 4.1.2 Publish DID Update This algorithm is called from 3.3 Update, if the beacon being used is of the type SingleUpdateBTCBeacon. A `didUpdateData` json object containing a set of DID document update deltas and a capability invocation authorizing these deltas. The beacon broadcasts this update by publishing it to **IPFS/A CAS?** and broadcasting a bitcoin transaction with a transaction output containing the CID value for retrieving the `didUpdataData`. 1. Initialize a `addressURI` variable to `beacon.serviceEndpoint` 2. Set `bitcoinAddress` to the decoding of `addressURI` following BIP21 3. Ensure `bitcoinAddress` is funded, if not fund this address 4. Construct a `cid` from the `didUpdateData` according to the `casType` 5. Publish the `didUpdateData` to an IPFS node. It is RECOMMENDED that this data is pinned you a node under your control 6. Initialize `spendTx` to a bitcoin transaction that spends from the `bitcoinAddress` to a single transaction output. The output should have the following format `[OP_RETURN, OP_PUSH32, cid]` 7. Broadcast `spendTx` to the bitcoin network ### 4.1.3 Process Beacon Signal This algorithm is called as part of the resolution (See 3.2.4 Process Beacon Updates) with `tx` passed in. 1. Initialize a `txOut` variable to `tx.txOuts[0]` 2. Check `txOut` is of the format [OP_RETURN, 32BYTE_CID], if not MUST raise `invalidBeaconSignal` error. 3. Set `cid` to the 32 bytes in `txOut`. 4. Set `didPayload` to the result of retrieving `cid` from IPFS? If not found MUST raise a `latePublishError`. > [name=Will Abramson Is the content addressable storage IPFS? Would we need different beacon types for different storage solutions?] 5. Return `didPayload` ![](https://hackmd.io/_uploads/HyIouRlka.jpg) ## 4.2 CIDAggregatedBTCBeacon > [color=red] **Decision Point:** How do we identify the CAS of a CID beacon? > Don't think using casType in each DID doc service is the best option. It is the coordinator that selects the CAS for the bundle. So enabling/requiring participants to specify this in DID doc could lead to errors. However, participants could still specify casType for their individual update data, with bundle just containing a bunch of CIDs. > Does that just leave specifying multiple beacon types? A beacon of the type CIDAggregatedBTCBeacon is a beacon that publishes bitcoin transactions containing a CID referencing an aggregated DID update bundle on IPFS. It is RECOMMENDED that this type of beacon is only included in a DID document if the DID controller is required to participate in the signing of bitcoin transactions from this beacon. In other words, this beacon SHOULD identify an n-of-n p2tr bitcoin address where m is the number of unique DID controllers submitting updates through the beacon. ### 4.2.1 Establish Beacon To establish a beacon, a cohort of cooperating parties SHOULD generate a n-of-n p2tr bitcoin address where each party contributes a public key. Furthermore, each party should verify that their key part of the address and all other keys part of the address are keys with controllers able to produce valid signatures. To establish a beacon there are two roles. One is the beacon participant, they want to join a beacon cohort and submit a request to do so with a key and proof of control over that key. The other is a coordinator, they curate beacon cohorts by combining beacon participants into cohorts, verifying proofs of control and producing beacon addresses. > Note: This is still very high level at the moment. Need to go deeper. E.g. what is the strucutre of these payloads that are broadcast and fetched. > Note: Difficult to represent in mermaid. Throws a syntax error, which I believe is because the participant and the coordinator actions are not joined up. ![](https://hackmd.io/_uploads/HkTJlpo33.jpg) #### 4.2.1.1 Create Beacon Advertisement > [color=red] **Decision Point:** How are beacons (or perhaps beacon coordinators) identified? Note also need mechanism to communicate to for both responsing to advert and submitting updates. > 1. Use DIDs. DID docs have specific service endpoint that identifies how beacon can be interacted with. Any entity may act in the role of coordinator, creating a beacon advertisement that they can broadcast across any medium. A beacon advert specifies the type of beacon that the coordinator intends to establish including: The beacon type, cohort size, update frequency and response latency. Additionally, the coordinator may specify a set of terms that all participants in the cohort must accept. Once the advert has been created and broadcast, the coordinator waits for enough participants to opt in in order to establish the beacon. #### 4.2.1.2 Beacon Opt-in DID controllers who wish to participate in a beacon first find potential beacon advertisements that meet their needs. This includes checking the beacon terms and update frequency etc. If satisfied, they create a secp256k1 cohort keypair and send an Opt-In response to the endpoint? specified in the adverstisement. **Note: Beacon opt-in needs to provide a return address. Is this another reason for providing a DID** > [color=red] **Decision Point**: > Should opt-in responses be required to provide the DID that they intend to include the beacon in? > Do we recommend that DID controllers use beacons for only a single DID rather than multiple DIDs they control. In otherwords does an n-of-n beacon only ever update at most a fixed set of n DIDs at a time? #### 4.2.1.3 Cohort Set Once a beacon coordinator has received enough opt-in responses from participants to satisfy the beacon properties they generate the n-of-n p2tr bitcoin address for the beacon. The address and all the cohort public keys the address is comprised of are then sent to all participants. #### 4.2.1.4 Add Beacon Service to DID document A participant recieving a cohort set message, verifies their cohort key is included in the cohort, calculates the p2tr beacon address for themselves and verifies it matches the address provided. They then can optionally wait until the beacon address is funded before adding the beacon as a service in the DID document. ```json { "id": "someid",// WHAT IS THE ID "type": "CIDAggregatedBTCBeacon", "serviceEndpoint": mmP2TRAddressUri } ``` ### 4.2.2 Publish DID Update This is an algorithm involving two roles. First a set of DID controllers submitting updates, second an aggregator collecting individual updates and aggregating them into a update bundle which is then published to a CAS and the CID for the bundle is included in a PSBT transaction output spent from the beacons n-of-n address. Each n parties in the beacon must sign the transaction before it can be broadcast to the network. ```mermaid sequenceDiagram autonumber Note left of CID Beacon Coordinator: Algorithm called with didUpdateInvocation<br/> and beacon object Note over Content Addressable Storage: CAS does not have to be the same as the one used to store individual didUpdateIvocations.<br/> Need more detail here. CID Beacon Coordinator->>CID Beacon Coordinator:Initialize CID bundle to empty object CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Identify beacon coordinator? CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Get casType from beacon.casType, if null use IPFS? CID Bundle Beacon Update Service->>Content Addressable Storage:Publish didUpdateInvocation Content Addressable Storage->>CID Bundle Beacon Update Service:CID CID Bundle Beacon Update Service->>CID Beacon Coordinator:Submit (DID, CID) CID Beacon Coordinator->>CID Beacon Coordinator:Add field DID with value CID to CID bundle object CID Beacon Coordinator->>CID Bundle Beacon Update Service:ack Note over CID Beacon Coordinator: Waits for conditions defined in the Beacon contract to be met.<br/> E.g. fixed time period or certain number of updates. CID Beacon Coordinator->>CID Beacon Coordinator:Wait ... CID Beacon Coordinator->>CID Beacon Coordinator:beacon contitions met CID Beacon Coordinator->>Content Addressable Storage:Publish CID Bundle Content Addressable Storage->>CID Beacon Coordinator:CID Note over CID Beacon Coordinator: Tx is a spend from the Beacon address to a TxOut of the format [OP_RETURN, CID] CID Beacon Coordinator->>CID Beacon Coordinator:Construct unsigned bitcoin tx CID Beacon Coordinator->>CID Bundle Beacon Update Service:Authorize beacon signal (tx) CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Check tx is a spend from expected beacon address CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Check single TxOut of format [OP_RETURN, 32B] CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Set bundleCid to the 32 Bytes in TxOut CID Bundle Beacon Update Service->>Content Addressable Storage:Fetch bundleCid Content Addressable Storage->>CID Bundle Beacon Update Service:bundle CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Check bundle exists CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Check bundle contains expected entry for DID. Note over CID Bundle Beacon Update Service: Entry should either be the CID previously submitted, or empty CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Pin bundleCid CID Bundle Beacon Update Service->>CID Bundle Beacon Update Service:Sign tx as PSBT CID Bundle Beacon Update Service->>CID Beacon Coordinator:Return PSBT CID Beacon Coordinator->>CID Beacon Coordinator:Collect all PSBT fragments from cohort CID Beacon Coordinator->>CID Beacon Coordinator:Combine PSBTs to create signed Bitcoin tx CID Beacon Coordinator->>Bitcoin node:Broadcast Bitcoin tx CID Beacon Coordinator->>CID Bundle Beacon Update Service:Signal broadcast (txId) ``` #### 4.2.2.1 Submit DID Update A DID controller creates a CID for the update they they wish to publish, then submits this CID along with the DID the update is for to a beacon coordinator for a beacon identified in their DID document. #### 4.2.2.2 Aggregate DID Updates A set of DID updates are aggregated together to create a update bundle. This bundle is published to the CAS(IPFS) and the CID for the bundle is included in a partially signed bitcoin transaction. This PSBT is the broadcast to all beacon cohort partipants for authoriation. #### 4.2.2.3 Authorize Beacon Signal On recieving an authorize beacon signal request, DID controllers must verifies the DID update bundle either includes an update the their DID that they submitted, or includes no update for their DID. Once satisfied, the DID controller signs the PSBT using the key they generated when establishing the beacon. #### 4.2.2.4 Broadcast Beacon Signal Once all beacon cohort participants have authorized the beacon signal by signing the PSBT, a valid, spendable bitcoin transaction can be created by aggregating the signatures following schnorr. This bitcoin transaction can then be broadcast to the network. ### 4.2.3 Process Beacon Signal A beacon signal is a bitcoin transaction with a CID referencing a bundle of DID updates. The bundle must first be retrieved and then the relevant DID update payload for the specific DID being resolved found and returned. If a CID cannot be found in the CAS at any point, a late publishing error MUST be raised. If an update cannot be found in the bundle for the relevant DID, then the beacon signal is ignored. 1. Initialize a `txOut` variable to `tx.txOuts[0]` 2. Check `txOut` is of the format [OP_RETURN, 32BYTE_CID], if not MUST raise `invalidBeaconSignal` error. 3. Set `cid` to the 32 bytes in `txOut`. 4. Initialize a `didUpdateBundle` variable to the result of retrieving the `cid` from IPFS. If unable to retrieve `cid` MUST throw a `latePublishError` and treat the DID being resolved as invalid. 5. Set `didUpdateCID` to the value of `didUpdateBundle[document.id]`. 6. If `didUpdateCID` is empty return null. (This beacon signal contains no update for the DID being resolved) 7. Set `didUpdatePayload` to the result of retrieving `didUpdateCID` from IPFS. If `didUpdateCID` not found MUST throw a `latePublishError`. 8. Return `didUpdatePayload` ![](https://hackmd.io/_uploads/HkZe90lkp.jpg) ## 4.3 SMTAggregatedBTCBeacon A SMTAggregatedBTCBeacon is a beacon whose signals are bitcoin transactions containing the root hash of a Sparse Merkle Tree (SMT). The SMT root hash attests to a set of did updates, however the updates themselves must be provided along with a proof of inclusion through a sidecar mechanism during resolution. Using the SMT root hash a resolver can then verify the inclusion proof for the given did update data. If a DID document includes a SMTAggregatedBTCBeacon in their set of beacon services, then they must provide proofs for each signal that the beacon broadcasts. If they did not update their DID in a signal, then they must provide a proof of non-inclusion for that signal. ### 4.3.1 Establish Beacon This algorithm is essentially the same as for the CIDAggregatedBTCBeacon. A cohort of DID controllers need to coordinate to produce a bitcoin address that will act as the beacon. It is RECOMMENDED this is a n-of-n p2tr address, with m being the set of DID controllers in the cohort. Once the address has been created, and all parties in the cohort acknowledge their intention to participate in that beacon. Each DID controller should add the beacon as a service to the DID document. ### 4.3.2 Publish DID Update To publish a DID update, the DID controller must get their update data included at their DIDs leaf in the Sparse Merkle Tree (SMT) and recieve an inclusion proof for this data. If a member of the beacon cohort does not wish to include a DID update in a beacon signal, they must recieve and verify a proof of non inclusion for their DID. Upon verifying the (non)inclusion proof against the SMT root hash, they should accept and authorize the bitcoin transaction containing the root hash. Once all members of the cohort have authorized the transaction, it can be broadcast to the network. DID controllers are responsible for persisting their did updates and proofs, likely they will need to provide these during a resolution process. ```mermaid sequenceDiagram autonumber Beacon Coordinator->>Beacon Coordinator:Initialize SMT with null values for all DIDs SMT Beacon Update Service->>SMT Beacon Update Service:Identify beacon coordinator? SMT Beacon Update Service->>Beacon Coordinator:Submit didUpateInvocation Beacon Coordinator->>Beacon Coordinator:Add didUpdateInvocation to SMT at leaf identified by DID Beacon Coordinator->>Beacon Coordinator:Wait ... Beacon Coordinator->>Beacon Coordinator:beacon contitions met Beacon Coordinator->>Beacon Coordinator:Calculate merle root of SMT Beacon Coordinator->>Beacon Coordinator:Calculate proof path for DID Beacon Coordinator->>Beacon Coordinator:Construct unsigned bitcoin tx Beacon Coordinator->>SMT Beacon Update Service:Signal prepared SMT Beacon Update Service->>SMT Beacon Update Service:Check spend from beacon address SMT Beacon Update Service->>SMT Beacon Update Service:Get SMT root from unsigned bticoin tx SMT Beacon Update Service->>SMT Beacon Update Service:Verify proofPath against SMT root for didUpdateInvocation SMT Beacon Update Service->>SMT Beacon Update Service:Partially sign tx SMT Beacon Update Service->>Beacon Coordinator:Partially signed bitcoin tx Beacon Coordinator->>Beacon Coordinator:Collect all PSBT fragments from beacon cohort Beacon Coordinator->>Beacon Coordinator:Combine PSBTs to create signed Bitcoin tx Beacon Coordinator->>Bitcoin node:Broadcast Bitcoin tx ``` ### 4.3.3 Process Beacon Signal Each beacon signal is extected to be a BTC transaction with a single transaction output. The output MUST be of the format [OP_RETURN, 32Bytes], where the 32 bytes are interpretted as a root to a sparse merkle tree of DID updates. To retrieve and validate a DID update payload for a specific DID, the resolver must recieve (out of band) the merkle proof and payload data for the DID. This is typically provided by the DID controller. Using the merkle root from the beacon signal, the resolver can check the proof gaining confidence that the payload provided is a valid update. The payload may be empty, in which case the proof is a proof of non-inclusion and this beacon signal has no valid information for the specific DID being resolved. ```mermaid sequenceDiagram autonumber Note left of Resolver: Algorithm called with a bitcoin tx and a **did:btc1** Note over Out of Band: Some entity, likely the DID controller<br/>MUST be able to provide a valid proofPath for a payload.<br/>Where the payoad is either a didUpdateInvocation or null. Resolver->>Resolver:Initialize txOut to tx.txOuts[0] Resolver->>Resolver:Check txOut is of the format [OP_RETURN, 32BYTE_SMT_ROOT], if not raise invalidBeaconSignal error Resolver->>Resolver:Set smtRoot to the 32 bytes in txOut Resolver->>Out of Band:Request SMT proof path and payload for did Out of Band->>Resolver:proofPath, payload Resolver->>Resolver:Verify proofPath for payload against smtRoot Resolver->>null:Return payload ``` ## 5. DID document Mutations/Deltas > [color=orange] This needs more work. Mutations to the DID document are represented using JSON0 transformations. This allows arbitrary transformations over JSON, rather than predefining a discrete set of operations for specific DID document mutations. This allows flexibility, but requires that the DID controller (or their software) be responsible for ensuring the DID document that results from applying the transformation remains a conformant DID document. ## 6. Distinguishing Features (Why is **did:btc1** better?) > [color=orange] TODO: Review these with Joe and refine text. Feel like I may be missing one. ### 6.1 No Late Publishing Late publishing, where the set of DID document updates creates a forked tree such that one path can appear valid at a certain point in time but subsequently seem to have never been valid, is expicitly prevented in this DID method. The set of DID updates relevant for a single DID MUST create a canonical, ordered sequence of DID updates. This is done by expicitly specifing the order that an update should be applied. Where there are dupicate updates found for the same order, updates must be equivalent or the DID is deemed to be invalid. We require the entire chain of updates. We are brittle to lost data. ### 6.2 Only Process Bitcoin Tx's Identified by Specific DID being Resolved The Bitcoin transactions a resolver must process are expicitly identified by the beacons defined in the DID's document over time. Each beacon identifies a bitcoin address, all spends from these addresses MUST be processed. However, there is no requirement to preprocess the entire bitcoin blockchain looking for all `**did:btc1**` beacon type transactions. Beacons and their relevant signals (bitcoin txs) can be identified, retrieved and processed during runtime on an as needed basis. There is no requirement for nodes to maintain a secondary network as in the sidetree case. This reduces the burden on resolvers, helping to prevent the centralization of resolution onto service providers with access to large infrastructure. ### 6.3 Substrate Independent Any substrate a beacon can refer to can be used to store updates and aggregated bundles. This enables sidecar, IPFS, or any other CID system. ### 6.4 Redundancy of Authority for Updates ### 6.5 No Trusted Authorities or Privelleged Actors **did:btc1** is designed to have no trusted authorities or node infrastructure requirements. Beacons are strongly recommended to be schnorr based m-of-m multi-sig addresses that require signatures from each party in the cohort. Every beacon included in a DID controllers DID document SHOULD be a beacon that requires authorization from a key under the control of the DID controller. This prevents malicious beacons from being able to post signals that invalidate the DIDs that rely on that beacon. ## 7. Limitations > [color=blue] **DISCUSS**: Suggested section. What are the limitations of this DID method and do we want to include such a section in the spec? ### 7.1 Aggregated Updates Have High Complexity Beacons that aggregate updates from many DID controllers, require an m-of-m signature to publish a bitcoin transaction from the beacon address. This multisig structure ensures that each DID controller must authorize all signals emitted by the beacon, preventing malicious beacon activity. However, coordinating an m-of-m multisig adds high communication complexity that increases with the size of m, the beacon cohort. Each member of the cohort must recieve a proposed beacon signal, verify its contents, contribute their part of the signing process and return this partially signed signal back to some coordinating entity. Once all members have returned valid signatures, they can be aggregated to create a valid spend from the beacon address on the bitcoin network. Furthermore, the PSBT logic required for schnorr based multi-sig has not yet been merged into Bitcoin core. ### 7.2 Protocol Cannot Enforce M-of-M Beacon Requirement A beacon is represented on the bitcoin network as a schnorr address. Spends from this address are treated as valid signals emitted from the beacon that must be processed as part of resolution. However, from a schnorr address alone it is not possible to tell if that address represents an m-of-m or 1-of-m or indeed any other variation of multisig. Therefore it is necessarily left to the responsibility of DID controllers to ensure they do not include beacons in their DID document that are able to emit signals without their authorization. Otherwise this may lead to late publishing or other attacks that invalidate the DID. ## 8. Recommended Best Practices > [color=blue] **DISCUSS**: Suggested section, is it useful? What are our recommended best practices and why. ### 8.1 Use multiple different beacons per DID (or even update?) ### 8.2 Be an active participant in beacons (require n-of-n) ### 8.3 Run Your Own Bitcoin Node ### 8.4 Always have a SingleUpdate beacon escape hatch ### 8.5 Persist All DID Update Related Information E.g. pin to IPFS. ## 9. Establish Beacon Algorithm Data Model Coordinator -> **BeaconAdvert** -> Broadcast Participant -> **OptIn** -> Coordinator Coordinator -> **CohortSet** -> Participants ### 9.1 Beacon Advert The parameters of a beacon need to be specified by the aggregator. These include: - Advert ID: Uniquely identifies the advert within the context of the aggregator - Frequency & Latency Requirements: How often the beacon will publish updates and how fast participants are required to respond. - Cohort Size: Number of participants, or min or max - Beacon Type: Whether the beacon is going to use the CID or SparseMerkleTree method to aggegate updates - Financials: - Subscription model - Pay-per-update - Communication Protocols - How does the aggregator reach contributors (for when/what) - How do contributors reach the aggregator (for when/what) - How do you confirm delivery? - Aggregator DID: Can be used to for establish secure communications - Signature: Signature over beacon payload from verification method in aggregators DID ### 9.2 OptIn Contains: - Advert ID: Uniquely identifies the advert within the context of the aggregator - Cohort Participation Public Key: Hex representation of a Secp256k1 public key - signature: A signature from the cohort particpation public key - return_interact?: How the aggregator can interact with participant - did? ### 9.3 CohortSet Contains - Advert ID: Unique ID for the beacon whose cohort has been set - Participant cohort keys: List of participant public keys (as hex strings) - Beacon Address: n-of-n p2tr beacon address - Signature ## 10. Update Capabilities > [color=orange] **TODO**: Review with Joe. Unsure about this structure, or what libraries I could use to attempt this. > The goal would be to invoke a root capability creating an invocation that verifies. Then drop the data structures into this document. > Not had great success with this at the moment. > [color=orange] **TODO**: Improve code examples > - Define context for capability invocation > - Define context for **did:btc1** > - Migrate from did:key to **did:btc1** in examples. > - Improve Secp256k1 did libraries. Need verification method and signature suite. > - Define algorithm to go from DID to the root capability for that DID. ### 10.1 Root capability For some DID string, you can deterministically generate the Root capability that must be invoked to update the DIDs document as follows. 1. Define `rootCapability` as an empty json. 2. Set `rootCapability['@context']` to 'https://w3id.org/zcap/v1' 3. Set `rootCapability.id` to `urn:zcap:root:${encodeURIComponent(DID)}`, 4. Set `rootCapability.controller` to DID 5. Set `rootCapability.invocationTarget` to DID ```json { '@context': 'https://w3id.org/zcap/v1', id: 'urn:zcap:root:did%3Akey%3Az6MkuUCMtGc31Ez1dG19PL8S4XHEfwBxZuWGBcFAjkEVByxr', controller: 'did:key:z6MkuUCMtGc31Ez1dG19PL8S4XHEfwBxZuWGBcFAjkEVByxr', invocationTarget: 'did:key:z6MkuUCMtGc31Ez1dG19PL8S4XHEfwBxZuWGBcFAjkEVByxr' } ``` ### 10.2 An Invocation of The Root For Update Two fields are added. Action, deltas and order. - updateTransformation: Is the object that encapsulates JSON0 transformation that mutates the DID document. - Version: The version is a number that dictates the order that the update in this invocation should be applied to a DID document. ```jsonld { '@context': [ 'https://w3id.org/security/v2', 'https://w3id.org/zcap/v1', 'https://w3id.org/security/suites/secp256k1-2019/v1' // **did:btc1** update context ], id: 'urn:uuid:cab83279-c695-4e66-9458-4327de49197a', updateTransformation: {'p': ['service', 3], 'li': {'id': '**did:btc1**:signet:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm#linked-domain', 'type': 'LinkedDomains', 'serviceEndpoint': 'https://bar.example.com'}}, version: 1, proof: { type: 'EcdsaSecp256k1Signature2019', created: '2023-11-22T19:17:48Z', verificationMethod: 'did:key:zQ3shes5Yp8MbQEHECiXp1ziq1WGnPJvKbQw2z8bMUjihyzWz#zQ3shes5Yp8MbQEHECiXp1ziq1WGnPJvKbQw2z8bMUjihyzWz', proofPurpose: 'capabilityInvocation', capability: 'urn:zcap:root:did%3Akey%3AzQ3shes5Yp8MbQEHECiXp1ziq1WGnPJvKbQw2z8bMUjihyzWz', invocationTarget: 'did:key:zQ3shes5Yp8MbQEHECiXp1ziq1WGnPJvKbQw2z8bMUjihyzWz', capabilityAction: 'write', proofValue: 'ziKx1CJLs4ek2CLAuZ72QFVrQJm3wjGhaRuAv6YYD2S66M4VgM48kriLJi3WKvU5yxAHg374mMFnxjuwDiZZp7Y8zDr1CoxofZb' } } ``` # Terminology The following terms are used in this specification. Capitalized terms either refer to terminology defined in this specification, e.g., Beacons, or to specific components defined in other specifications, e.g., Decentralized Identifers and Verifiable Credentials. * Aggregator * Cohort * Beacon * Beacon Signal * Beacon Address * Sidecar * Decentralized Identifiers * DID documents * Verifiable Credentials # Decisions Decisions can be point throughout the document. They identify architectural choices that necessarily constrain the design. For example whether **did:btc1** sidecar initial DID documents. Decisions are labelled through the document as: > [color=red] **Decision**: # Discussion Discussion points are labelled throughout the document as: > [color=blue] **Discuss**: - [ ] Document capability invocation approach to authorizing and verifying updates - [ ] What is the root capability? - [ ] What does a capability invocation object for an DID update look like? - [ ] It seems PSBT for taproot (BIP371) has not been merged in Bitcoin core yet. There is a reference implementation here - https://github.com/achow101/bitcoin/tree/taproot-psbt # TODOs See also TODOs added inline throughout the text in the format: > [color=orange] **TODO**: ... - [ ] Define and document the structure of a DID update deltas - [ ] Define and document the capability invocation that represents an update - [ ] Explore adding an onchain ordinal-style option - [ ] New terms: - [ ] DID doc: implicit, delta, full - [ ] Located: Onchain, implicit, sidecar, cid - [ ] Back of envolope estimates for usage. - [ ] Cost challenges for updating a determinstic DID to support aggregation # Implementation Gaps In order to support this did method there are a number of prerequisite features that must be implemented first. - [ ] Define JSON-LD context for **did:btc1**. Specifically adding the beacon serviceEndpoints - [ ] Define JSON-LD context for a **did:btc1** updatePayload. Need to specify the fields for the update itself (JSON0?) and the update number. - [ ] Develop libraries for constructing and applying a DID Update delta (JSON0?) - [ ] Develop / improve libraries for Secp256k1VerificationMethod and SignatureSuite using DataIntegrity - [ ] Define protocol for coordinating aggregated beacons - [ ] Message payloads - [ ] Communication Medium (nostr?) - [ ] Sparse Merkle Tree Variant POC - [ ] Identify SMT library

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully