The logic for computing canonical references conflated the semantics of annotated and lighweight tags, yielding confusing/wrong results. The main culprit was the call to `peel_to_commit` in `impl ReadRepository for Repository`, peeling tag objects away. To resolve this, we separate out quroum computation per object type: one implementation for commits, and one for tags. Also move move canonical error types and methods into their own module to have a cleaner file structure for the main logic. Capture the `BTreeMap<Oid, u8>` type into a `Votes` struct, with its own API. We were getting the objects from the repository twice – once in `Canonical::new` and once again in `ensure_commit_or_tag` – so the latter was removed. Use an `enum CanonicalObject` to specify which object types the canonical process supports. During `converges`, separate commits and tags, and ensure that we are only looking at objects of one type. Note, that Fintan think this is actually the *wrong* place to do it because we already filter the objects – so we should keep track of that information higher up the callstack. Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
8.9 KiB
In the attempt below, to update the identity, we can see that a threshold of 2 delegates cannot be met when Alice attempts to do
this. This is because she requires Bob's default branch to ensure that
the threshold can be met and the canonical version of the default
branch (refs/heads/<default branch> at the top-level of the storage)
can be updated.
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --threshold 2
✗ Error: failed to verify delegates for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
✗ Error: the threshold of 2 delegates cannot be met..
✗ Error: the delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk is missing
✗ Hint: run `rad follow did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk` to follow this missing peer
✗ Error: fatal: refusing to update identity document
Instead, Alice can simply keep the threshold as 1 and still add Bob as a delegate:
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
✓ Identity revision 7be665f9fccba97abb21b2fa85a6fd3181c72858 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Bob │
│ Revision 7be665f9fccba97abb21b2fa85a6fd3181c72858 │
│ Blob 93d3009787e5d8a481dffc4dd248ea46af592466 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
│ │
│ Add Bob as a delegate │
├────────────────────────────────────────────────────────────────────────┤
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
@@ -1,13 +1,14 @@
{
"payload": {
"xyz.radicle.project": {
"defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
},
"delegates": [
- "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
],
"threshold": 1
}
Alice can still make changes to her working copy, change the canonical head, and make patches -- as we can see below:
$ touch REQUIREMENTS
$ git add REQUIREMENTS
$ git commit -v -m "Define power requirements"
[master 3e674d1] Define power requirements
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 REQUIREMENTS
$ git push rad master
✓ Canonical reference refs/heads/master updated to target commit 3e674d1a1df90807e934f9ae5da2591dd6848a33
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..3e674d1 master -> master
$ rad sync -a
✓ Synced with 1 seed(s)
$ git checkout -b add-readme
$ touch README.md
$ git add README.md
$ git commit -v -m "Add README file"
[add-readme 964513c] Add README file
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
$ git push rad HEAD:refs/patches
✓ Patch b09b2aa0ee055671c811e9ad4ba73eed211ebaa3 opened
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
Any other seeds can also still fetch changes from Alice without any errors:
$ rad sync rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji -f
Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
We can also inspect the repository to ensure all the data is consistent with the change made to the identity.
The identity has the new delegate, while the threshold is still 1
$ rad inspect --identity
{
"payload": {
"xyz.radicle.project": {
"defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
],
"threshold": 1
}
Alice only sees her refs, since she has not synced with Bob's references yet:
$ rad inspect --refs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ ├── xyz.radicle.id
│ │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
│ └── xyz.radicle.patch
│ └── b09b2aa0ee055671c811e9ad4ba73eed211ebaa3
├── heads
│ ├── master
│ └── patches
│ └── b09b2aa0ee055671c811e9ad4ba73eed211ebaa3
└── rad
├── id
├── root
└── sigrefs
Similarly, she still does not have Bob's rad/sigrefs:
$ rad inspect --sigrefs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi ae3c6b77dc1ed51c1c1e6a2772339c2779fa9ba8
And she can still list the project, without any worries:
$ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public 3e674d1 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Once Bob clones the repository and creates a fork, i.e. creates a
branch to refs/heads/master for this project, she can then use rad sync and fetch his references:
$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'all'
Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
✓ Repository successfully cloned under [..]/bob/heartwood/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 0 issues · 1 patches │
╰────────────────────────────────────╯
Run `cd ./heartwood` to go to the repository directory.
$ cd heartwood
$ rad fork
✓ Forked repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad sync -f
Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad inspect --sigrefs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi ae3c6b77dc1ed51c1c1e6a2772339c2779fa9ba8
z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk dace6fe948548168a2bb687718949d9b5d9076ee