Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docs to describe new governance API #5713

Merged
merged 11 commits into from
Oct 6, 2023
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[5.0.0-dev3]: https://github.com/microsoft/CCF/releases/tag/ccf-5.0.0-dev3

- Added a `consensus.max_uncommitted_tx_count` configuration option, which specifies the maximum number of transactions that can be pending on the primary. When that threshold is exceeded, a `503 Service Unavailable` is temporarily returned on all but the `/node/*` paths (#5692).
- A new versioned governance API is now available, with the `api-version=2023-06-01-preview` query parameter. This will fully replace the previous governance endpoints, which will be removed in a future release.
- A new versioned governance API is now available, with the `api-version=2023-06-01-preview` query parameter. This will fully replace the previous governance endpoints, which will be removed in a future release. A guide to aid in upgrading from the previous API is available [here](https://microsoft.github.io/CCF/main/governance/gov_api_schemas/upgrading_from_classic.html)
eddyashton marked this conversation as resolved.
Show resolved Hide resolved

## [5.0.0-dev2]

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ configure_file(
@ONLY
)

file(READ ${CCF_DIR}/src/node/gov/2023-06-01-preview.json
file(READ ${CCF_DIR}/doc/schemas/mccf/2023-06-01-preview/mccfgov.json
eddyashton marked this conversation as resolved.
Show resolved Hide resolved
GOV_API_SCHEMA_2023_06_01_PREVIEW
)
configure_file(
Expand Down
2 changes: 1 addition & 1 deletion doc/build_apps/run_app.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ This should look much like a standard HTTP server, with error codes for missing
$ curl https://127.0.0.1:8000/app/not/a/real/resource -X GET --cacert service_cert.pem --cert user0_cert.pem --key user0_privk.pem -i
HTTP/1.1 404 Not Found

$ curl https://127.0.0.1:8000/gov/proposals -X POST --cacert service_cert.pem --cert user0_cert.pem --key user0_privk.pem -i
$ curl https://127.0.0.1:8000/gov/members/proposals:create?api-version=2023-06-01-preview -X POST --cacert service_cert.pem --cert user0_cert.pem --key user0_privk.pem -i
HTTP/1.1 403 Forbidden

Logging App Commands
Expand Down
139 changes: 85 additions & 54 deletions doc/governance/accept_recovery.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,57 @@ A member proposes to recover the network and other members can vote on the propo

.. code-block:: bash

$ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member1_privk.pem --signing-cert member1_cert.pem --content transition_service_to_open.json | \
curl https://<ccf-node-address>/gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose"
$ ccf_cose_sign1 \
--ccf-gov-msg-type proposal \
--ccf-gov-msg-created_at `date -uIs` \
--signing-key member1_privk.pem \
--signing-cert member1_cert.pem \
--content transition_service_to_open.json \
| curl https://<ccf-node-address>/gov/members/proposals:create?api-version=2023-06-01-preview \
--cacert service_cert.pem \
--data-binary @- \
-H "content-type: application/cose"
{
"ballot_count": 0,
"proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"state": "Open"
"ballotCount": 0,
"proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"proposalState": "Open"
}
eddyashton marked this conversation as resolved.
Show resolved Hide resolved

$ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 --signing-key member1_privk.pem --signing-cert member1_cert.pem --content vote_accept.json | \
curl https://<ccf-node-address>/gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose"
$ ccf_cose_sign1 \
--ccf-gov-msg-type ballot \
--ccf-gov-msg-created_at `date -uIs` \
--ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 \
--signing-key member1_privk.pem \
--signing-cert member1_cert.pem \
--content vote_accept.json \
| curl https://<ccf-node-address>/gov/members/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1:submit?api-version=2023-06-01-preview \
--cacert service_cert.pem \
--data-binary @- \
-H "content-type: application/cose"
{
"ballot_count": 1,
"proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"state": "Open"
"ballotCount": 1,
"proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"proposalState": "Open"
}

$ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 --signing-key member2_privk.pem --signing-cert member2_cert.pem --content vote_accept.json | \
curl https://<ccf-node-address>/gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose"
$ ccf_cose_sign1 \
--ccf-gov-msg-type ballot \
--ccf-gov-msg-created_at `date -uIs` \
--ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 \
--signing-key member2_privk.pem \
--signing-cert member2_cert.pem \
--content vote_accept.json
| curl https://<ccf-node-address>/gov/members/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/e306e3a6eead2f4a3854302b41c3015bf12db9535ac0be1b8cf6584f84bca92b:submit?api-version=2023-06-01-preview \
--cacert service_cert.pem \
--data-binary @- \
-H "content-type: application/cose"
{
"ballot_count": 2,
"proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"state": "Accepted"
"ballotCount": 2,
"proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"proposalState": "Accepted"
}

Once the proposal to recover the network has passed under the rules of the :term:`Constitution`, the recovered service is ready for members to submit their recovery shares.
Expand All @@ -67,27 +93,35 @@ To restore private transactions and complete the recovery procedure, recovery me

.. note:: The recovery members who submit their recovery shares do not necessarily have to be the members who previously accepted the recovery.

Member recovery shares are stored in the ledger, encrypted with each member's public encryption key. Members can retrieve their encrypted recovery shares from the public-only service via the :http:GET:`/gov/encrypted_recovery_share/{member_id}` endpoint, perform the share decryption securely (see for example :doc:`hsm_keys`) and submit the decrypted recovery share via the :http:POST:`/gov/recovery_share` endpoint.
Member recovery shares are stored in the ledger, encrypted with each member's public encryption key. Members can retrieve their encrypted recovery shares from the public-only service via the :http:GET:`/gov/recovery/encrypted-shares/{memberId}` endpoint, perform the share decryption securely (see for example :doc:`hsm_keys`) and submit the decrypted recovery share via the :http:POST:`/gov/recovery/members/{memberId}:recover` endpoint.

The recovery share retrieval, decryption and submission steps can be conveniently performed in one step using the ``submit_recovery_share.sh`` script:

.. code-block:: bash

$ submit_recovery_share.sh https://<ccf-node-address> --member-enc-privk member0_enc_privk.pem --cert member0_cert.pem
--key member0_privk.pem --cacert service_cert.pem
$ submit_recovery_share.sh https://<ccf-node-address> \
--member-enc-privk member0_enc_privk.pem \
--cert member0_cert.pem \
--api-version 2023-06-01-preview \
--key member0_privk.pem \
--cacert service_cert.pem
HTTP/1.1 200 OK
content-type: text/plain
x-ms-ccf-transaction-id: 4.28
1/2 recovery shares successfully submitted.

$ submit_recovery_share.sh https://<ccf-node-address> --member-enc-privk member1_enc_privk.pem --cert member1_cert.pem
--key member1_privk.pem --cacert service_cert.pem
$ submit_recovery_share.sh https://<ccf-node-address> \
--member-enc-privk member1_enc_privk.pem \
--cert member1_cert.pem \
--api-version 2023-06-01-preview \
--key member1_privk.pem \
--cacert service_cert.pem
HTTP/1.1 200 OK
content-type: text/plain
x-ms-ccf-transaction-id: 4.30
2/2 recovery shares successfully submitted. End of recovery procedure initiated.

When the recovery threshold is reached, the :http:POST:`/gov/recovery_share` endpoint signals that the end of the recovery procedure is initiated and the that private ledger is now being recovered. Operators and members can monitor the progress of the private recovery process via the :http:GET:`/node/state` endpoint.
When the recovery threshold is reached, the :http:POST:`/gov/recovery/members/{memberId}:recover` response signals that the end of the recovery procedure is initiated and that the private ledger is now being recovered. Operators and members can monitor the progress of the private recovery process via the :http:GET:`/node/state` endpoint.

.. note:: While all nodes are recovering the private ledger, no new transaction can be executed by the network.

Expand All @@ -101,33 +135,30 @@ Summary Diagram
.. mermaid::

sequenceDiagram
participant Member 0
participant Member 1
participant Users
participant Node 2
participant Node 3

Note over Node 2, Node 3: Operators have restarted a public-only service

Member 0->>+Node 2: Propose transition_service_to_open
Node 2-->>Member 0: Proposal ID
Member 1->>+Node 2: Vote for Proposal ID
Node 2-->>Member 1: State: Accepted
Note over Node 2, Node 3: transition_service_to_open proposal completes. <br> Service is ready to accept recovery shares.

Member 0->>+Node 2: GET /gov/encrypted_recovery_share/<member0_id>
Node 2-->>Member 0: Encrypted recovery share for Member 0
Note over Member 0: Decrypts recovery share
Member 0->>+Node 2: POST /gov/recovery_share: "<recovery_share_0>"
Node 2-->>Member 0: 1/2 recovery shares successfully submitted.

Member 1->>+Node 2: GET /gov/encrypted_recovery_share/<member1_id>
Node 2-->>Member 1: Encrypted recovery share for Member 1
Note over Member 1: Decrypts recovery share
Member 1->>+Node 2: POST /gov/recovery_share: "<recovery_share_1>"
Node 2-->>Member 1: End of recovery procedure initiated.

Note over Node 2, Node 3: Reading Private Ledger...

Note over Node 2: Recovery procedure complete
Note over Node 3: Recovery procedure complete
participant Member A
participant Member B
participant Network

Note over Network: Operators have restarted a public-only service

Member A->>+Network: Propose transition_service_to_open
Network-->>Member A: Proposal ID
Member B->>+Network: Vote for Proposal ID
Network-->>Member B: State: Accepted

Note over Network: transition_service_to_open proposal completes. <br> Service is ready to accept recovery shares.

Member A->>+Network: GET /gov/recovery/encrypted-shares/<member0_id>
Network-->>Member A: Encrypted recovery share for Member A
Note over Member A: Decrypts recovery share
Member A->>+Network: POST /gov/recovery/members/<member0_id>:recover": "<recovery_share_0>"
Network-->>Member A: 1/2 recovery shares successfully submitted.

Member B->>+Network: GET /gov/recovery/encrypted-shares/<member1_id>
Network-->>Member B: Encrypted recovery share for Member B
Note over Member B: Decrypts recovery share
Member B->>+Network: POST /gov/recovery/members/<member1_id>:recover": "<recovery_share_1>"
Network-->>Member B: End of recovery procedure initiated.

Note over Network: Reading Private Ledger...
Note over Network: Recovery procedure complete
41 changes: 26 additions & 15 deletions doc/governance/adding_member.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The CCF unique member identity is the hex-encoded string of the SHA-256 hash of

$ identity_cert_path=/path/to/member/cert
$ openssl x509 -in "$identity_cert_path" -noout -fingerprint -sha256 | cut -d "=" -f 2 | sed 's/://g' | awk '{print tolower($0)}'
7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6

.. note:: See :ref:`architecture/cryptography:Algorithms and Curves` for the list of supported cryptographic curves for member identity.

Expand All @@ -49,37 +50,47 @@ Activating a New Member

A new member who gets registered in CCF is not yet able to participate in governance operations. To do so, the new member should first acknowledge that they are satisfied with the state of the service (for example, after auditing the current constitution and the nodes currently trusted).

First, the new member should update and retrieve the latest state digest via the :http:POST:`/gov/ack/update_state_digest` endpoint. In doing so, the new member confirms that they are satisfied with the current state of the service.
First, the new member should update and retrieve the latest state digest via the :http:POST:`/gov/members/state-digests/{memberId}:update` endpoint. In doing so, the new member confirms that they are satisfied with the current state of the service.

.. code-block:: bash

$ curl https://<ccf-node-address>/gov/ack/update_state_digest -X POST --cacert service_cert.pem --key new_member_privk.pem --cert new_member_cert.pem --silent | jq > request.json
$ curl https://<ccf-node-address>/gov/members/state-digests/7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6:update?api-version=2023-06-01-preview \
-X POST \
--cacert service_cert.pem \
--key new_member_privk.pem \
--cert new_member_cert.pem \
--silent | jq > request.json
$ cat request.json
{
"state_digest": <...>
"digest": <...>
}


Then, the new member should sign the state digest returned by the :http:POST:`/gov/ack/update_state_digest` via the :http:POST:`/gov/ack` endpoint, using the ``ccf_cose_sign1`` utility:
Then, the new member should sign the state digest returned by :http:POST:`/gov/members/state-digests/{memberId}:update` (or :http:GET:`/gov/members/state-digests/{memberId}`) via the :http:POST:`/gov/members/state-digests/{memberId}:ack` endpoint, using the ``ccf_cose_sign1`` utility:

.. code-block:: bash

$ ccf_cose_sign1 --ccf-gov-msg-type ack --ccf-gov-msg-created_at `date -uIs` --signing-key new_member_privk.pem --signing-cert new_member_cert.pem --content request.json | \
curl https://<ccf-node-address>/gov/ack --cacert service_cert.pem --data-binary @- -H "content-type: application/cose"
true
$ ccf_cose_sign1 \
--ccf-gov-msg-type ack \
--ccf-gov-msg-created_at `date -uIs` \
--signing-key new_member_privk.pem \
--signing-cert new_member_cert.pem \
--content request.json \
| curl https://<ccf-node-address>/gov/members/state-digests/7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6:ack?api-version=2023-06-01-preview \
--cacert service_cert.pem \
--data-binary @- \
-H "content-type: application/cose"

Once the command completes, the new member becomes active and can take part in governance operations (e.g. creating a new proposal or voting for an existing one). You can verify the activation of the member at `/gov/members`.
Once the command completes, the new member becomes active and can take part in governance operations (e.g. creating a new proposal or voting for an existing one). You can verify the activation of the member at :http:GET:`/gov/service/members/{memberId}`.

.. code-block:: bash

$ curl https://<ccf-node-address>/gov/members --silent | jq
$ curl https://<ccf-node-address>/gov/service/members/7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6?api-version=2023-06-01-preview?api-version=2023-06-01-preview --silent | jq
{
"<member_id>": {
"cert": <...>,
"member_data": <...>,
"public_encryption_key": <...>,
"status": "Active"
}
"memberId": "7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6",
"certificate": <...>,
"memberData": <...>,
"status": "Active"
}

.. note:: The newly-activated member is also given a recovery share that can be used :ref:`to recover a defunct service <governance/accept_recovery:Submitting Recovery Shares>`.
Loading
Loading