owned this note
owned this note
Published
Linked with GitHub
# Decisions
Decisions can be point throughout the document. They identify architectural choices that necessarily constrain the design. For example whether did:btc 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:btc. Specifically adding the beacon serviceEndpoints
- [ ] Define JSON-LD context for a did:btc 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
# Abstract
# 1. Introduction
did:btc is the bitcoin DID method. It uses bitcoin as a verifiable data registry to store canonical status for a new type of DID.
did:btc is designed to be secure, flexible and resilient. It supports offline creation and directed aggregated updates as well as direct, single DID updates, all without late publishing and without requiring public disclosure of DID documents.
* Offline creation allows creating DIDs without interacting with the blockchain.
* Aggregated updates allow an arbitrary number of DID document updates to be combined by an agregator and posted to bitcoin in a single transaction.
* Directed aggregated updates means that resolving parties need only process transactions likely to contain updates for specific DID
* Late publishing is avoided by ensuring 100% 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.
did:btc supports offline creation in two modes:
* deterministically from a key pair and
* from an arbitrary initial DID document.
Deterministic creation means that the DID itself encodes a cryptographic seed that can be used to automatically generate the entire initiating DID Document.
Initial 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 must have it provided directly.
Once created, a did:btc's DID document can then be updated by posting a signed update bundle to a "beacon" specified in the current DID document.
Beacons are the key mechanism for resilient, aggregatable discovery of updates. Specified in the current DID Document, beacons tell resolving parties where to check for updates. In this version of did:btc *all* beacons are addresses on bitcoin and all the resolver has to do is watch those addresses for any transactions. Spends from those addresses indicate an update, with the appropriate details for how to get the update bundle for processing.
Because each DID document specifies which Beacons a resolver should check, resolvers need only process the transactions that are valid spends from the Beacon's bitcoin address.
Every update to the DID Document is made by a signed update published by one or more beacons. The signed update includes a content reference to the prior version, 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 then controller of the DID.
JOE: CONTINUE FROM HERE
broadcasting a cryptographic invocations that define and authorize transformations which must be applied to the current DID document in a specified, canonical ordering. Updates are broadcast through a mechanism referred to as Beacons, which are included in the service array of the DID document. All beacons have a type, which defines how to estabish a beacon, how to submit an update to a beacon and how to process signals broadcast from a beacon. The beacons initially considered in this specification are identified by a bitcoin address and broadcast their signals through spends from that address included within the bitcoin blockchain. Resolution requires identifying the beacons in the service array of a DID document, then fetching and processing all signals from these beacons to retrieve individual update invocations for the specific DID being resolved. Invocations are then verified before the update transformations are applied in their defined canonical order until all beacon signals have been processed.
# 2. did:btc ABNF
> [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
The format for the did:btc method conforms to the [DID CORE](https://www.w3.org/TR/did-core/) specification. It consists of a `did:btc` 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 the method specific identifier is as follows:
```abnf
did-btc = "did:btc:" [ 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:btc:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm - MOST COMMON
* did:btc:1:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm
* did:btc:mainnet:8NxqnpZ8qei2yaAGGT9vMPPka8AEHBMJcdDMjc9nV9ykzyxyjm
* did:btc: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:btc:<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:btc 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:btc:<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?
## 3.2 Read
<div id="did_resolution"/>
The read method, takes a did:btc `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:btc context
- Set `document['@context]' to contextArray`
> [color=orange] **TODO**: Define a did:btc 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:btc. 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:btc 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:btc 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:btc 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:btc 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:btc
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:btc 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:btc` 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:btc 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:btc
> - Migrate from did:key to did:btc 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:btc update context
],
id: 'urn:uuid:cab83279-c695-4e66-9458-4327de49197a',
updateTransformation: {'p': ['service', 3],
'li': {'id': 'did:btc: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'
}
}
```