@dashevo/moderation-charters-contract 4.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.yml +2 -0
- package/Cargo.toml +15 -0
- package/LICENSE +20 -0
- package/README.md +118 -0
- package/eslint.config.mjs +10 -0
- package/lib/systemIds.js +4 -0
- package/package.json +27 -0
- package/schema/v1/moderation-charters-contract-documents.json +641 -0
- package/src/error.rs +17 -0
- package/src/lib.rs +196 -0
- package/src/v1/mod.rs +146 -0
- package/test/bootstrap.js +30 -0
- package/test/unit/moderationChartersContract.spec.js +465 -0
package/.mocharc.yml
ADDED
package/Cargo.toml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "moderation-charters-contract"
|
|
3
|
+
description = "Moderation charters data contract schema and tools. A team's application to moderate a contract"
|
|
4
|
+
version.workspace = true
|
|
5
|
+
edition = "2021"
|
|
6
|
+
rust-version.workspace = true
|
|
7
|
+
license = "MIT"
|
|
8
|
+
|
|
9
|
+
[dependencies]
|
|
10
|
+
thiserror = "2.0.12"
|
|
11
|
+
platform-version = { path = "../rs-platform-version" }
|
|
12
|
+
serde_json = { version = "1.0" }
|
|
13
|
+
platform-value = { path = "../rs-platform-value" }
|
|
14
|
+
[dev-dependencies]
|
|
15
|
+
base58 = "0.2.0"
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Dash Core Group, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Moderation Charters Contract
|
|
2
|
+
|
|
3
|
+
The moderation charters system contract holds the charters of the moderation
|
|
4
|
+
teams that masternodes elect for data contracts that declare an elected
|
|
5
|
+
moderation team. It activates at protocol version 14, registered at genesis by
|
|
6
|
+
chains born at 14 and inserted by the upgrade to 14, and has the same ID on
|
|
7
|
+
every network: `EG7RGfV8fDTayC2FyVr8HwdpJh3fXDbVztcfE94UmN88`.
|
|
8
|
+
|
|
9
|
+
It has seven document types. All are immutable. The four a charter is made of
|
|
10
|
+
(`reason`, `submittedCharter`, `joinRequest`, `electedCharter`) are
|
|
11
|
+
undeletable, so everything a charter points at, and the charter itself, is a
|
|
12
|
+
fixed text; the three team changes are deletable.
|
|
13
|
+
|
|
14
|
+
The schema carries almost every rule through its keywords: typed arrays with
|
|
15
|
+
a reference per element, a reference resolved through a unique index
|
|
16
|
+
(`lookup`), `distinctFrom`, key requirements on key references, the
|
|
17
|
+
`encryptedFor` envelope, `maxBytes` for the description's 4096-byte cap and a
|
|
18
|
+
`propertyConstraints` rule holding the reward split to 100. What it cannot say,
|
|
19
|
+
the cap on additions, is checked by the batch's state validation, and
|
|
20
|
+
`SubmittedCharter` in `rs-dpp` only reads a proposal.
|
|
21
|
+
|
|
22
|
+
Seating writes nothing. Awarding the contest for a target writes the winning
|
|
23
|
+
`electedCharter` here, the only one ever written for that target, and the
|
|
24
|
+
target's moderation paths read it: its team moderates instead of the interim
|
|
25
|
+
moderators, is protected, and may charge its proposal's `moderatorsShare` of a
|
|
26
|
+
declared moderators fee (see [the protocol guide](../../docs/protocol/moderation-charters.md#seating)).
|
|
27
|
+
|
|
28
|
+
## `reason`
|
|
29
|
+
|
|
30
|
+
A ground for a moderation action. Anyone may file one.
|
|
31
|
+
|
|
32
|
+
| Property | Type | Meaning |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `code` | string, 3 uppercase letters, required | Unique among the owner's reasons (`byOwnerCode`); what an action shows. An action names a reason by document id (`reasonDocumentId`), and a seated team only one its proposal lists (41203) |
|
|
35
|
+
| `label` | string, 1 to 64 characters, required | The reason's name |
|
|
36
|
+
| `description` | string, 1 to 1024 characters | What the reason covers and how the team applies it |
|
|
37
|
+
|
|
38
|
+
## `submittedCharter`
|
|
39
|
+
|
|
40
|
+
A leader's proposal to moderate one contract, on the contract's own terms:
|
|
41
|
+
the target's elected moderation declaration is the team's whole mandate, so
|
|
42
|
+
the proposal names no abilities. Its owner is the leader, and must hold a
|
|
43
|
+
decryption key bound to this type so join requests can be encrypted to it.
|
|
44
|
+
|
|
45
|
+
| Property | Type | Meaning |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `targetContractId` | identifier, required, `refersTo` a contract with elected moderation | The contract the team proposes to moderate |
|
|
48
|
+
| `description` | string, 1 to 4096 characters and at most 4096 bytes, required | What the team would moderate and how. Informational |
|
|
49
|
+
| `reasons` | array of at most 64 unique reason ids, required, each `refersTo` a `reason` | The moderation reasons the team's actions may name; a team with none can take no action |
|
|
50
|
+
| `moderatorsShare` | integer 0 to 100 | The percentage of each moderated type's declared moderators fee the team takes; absent is the full amount, 0 a team that will not moderate and takes no rewards |
|
|
51
|
+
| `rewardSplit` | object, required | `leader`, `equal` and `actions` percentages summing to 100 (the `rewardSplitIsWhole` rule of `propertyConstraints`): how every settle of the target's moderators pot is paid out, a claim or a team change |
|
|
52
|
+
|
|
53
|
+
Indexes: `byTargetContract` (target, `$createdAt`) lists the proposals for a
|
|
54
|
+
contract in filing order; `byOwner` lists a leader's proposals.
|
|
55
|
+
|
|
56
|
+
## `joinRequest`
|
|
57
|
+
|
|
58
|
+
An identity's offer to serve on the team of a proposal, one per identity per
|
|
59
|
+
proposal (`bySubmittedCharter`, unique on the proposal and the owner), with a
|
|
60
|
+
message only the leader can read. The owner must hold an encryption key bound
|
|
61
|
+
to this type.
|
|
62
|
+
|
|
63
|
+
| Property | Type | Meaning |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `submittedCharterId` | identifier, required, `refersTo` a `submittedCharter` | The proposal; `recipientId` must equal its owner (`propertyAgreement`) |
|
|
66
|
+
| `recipientId` | identifier, required, `refersTo` an identity public key through `recipientKeyId` | The leader and the decryption key the message is encrypted to |
|
|
67
|
+
| `recipientKeyId` | integer, required | The leader's key id |
|
|
68
|
+
| `senderKeyId` | integer, required | The owner's encryption key the shared secret is derived from |
|
|
69
|
+
| `encryptedMessage` | bytes, 32 to 1040, required | Why the owner wants to join, encrypted for the leader (ECDH on secp256k1, AES-256-CBC) |
|
|
70
|
+
|
|
71
|
+
## `electedCharter`
|
|
72
|
+
|
|
73
|
+
A proposal put to the vote with its team: the only type that opens or joins
|
|
74
|
+
the contest for a target. Only the proposal's leader may create one, for the
|
|
75
|
+
proposal's own target (`propertyAgreement` on `$ownerId` and
|
|
76
|
+
`targetContractId`). The `byTargetContract` index is a contested unique index
|
|
77
|
+
keyed by the target contract with resolution `1`, the vote without a Lock
|
|
78
|
+
choice by masternodes (weight 1) and evonodes (weight 4): a create on it
|
|
79
|
+
opens or joins the contest, a tie goes to the earliest applicant, and a
|
|
80
|
+
single applicant is seated when the join window closes. `bySubmittedCharter`
|
|
81
|
+
lists the elected charters of a proposal. It is not unique: a type with a
|
|
82
|
+
contested unique index may carry no other unique index, and none is needed,
|
|
83
|
+
since an identity may contend once per contest and only the proposal's owner
|
|
84
|
+
may enter it, so a proposal has at most one contender at a time. The seated
|
|
85
|
+
leader and members act with the target's full mandate; there are no powers.
|
|
86
|
+
|
|
87
|
+
| Property | Type | Meaning |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `targetContractId` | identifier, required, `refersTo` a contract whose election is open | The contract contended for; its own `electionDelay` since its creation must have passed |
|
|
90
|
+
| `submittedCharterId` | identifier, required, `refersTo` a `submittedCharter` | The proposal the team runs on |
|
|
91
|
+
| `members` | array of at most 15 unique identity ids, required, each the owner of a `joinRequest` for this proposal (`lookup`) and none the leader (`distinctFrom`) | The team besides the leader; may be empty |
|
|
92
|
+
|
|
93
|
+
## After the election
|
|
94
|
+
|
|
95
|
+
Once an elected charter is seated, its team can change without a new vote:
|
|
96
|
+
|
|
97
|
+
| Type | Written by | Properties | Rules |
|
|
98
|
+
| --- | --- | --- | --- |
|
|
99
|
+
| `addedModerator` | the leader | `electedCharterId`, `submittedCharterId`, `memberId` | `memberId` owns a `joinRequest` for the charter's proposal (`lookup`) and is not the leader; at most the target's `maxAddedModerators` additions per charter at a time, a consensus rule of the batch's state validation (41202); deleting it takes the member off and frees its slot |
|
|
100
|
+
| `removedModerator` | the leader | `electedCharterId`, `memberId` | Needs no resignation; `memberId` is one of the charter's elected `members` (`listElement`); deleting it puts the member back |
|
|
101
|
+
| `resignationRequest` | a member of the team | `electedCharterId`, `recipientId`, `recipientKeyId`, `senderKeyId`, `encryptedMessage` | The writer is in the charter's `members` or has an addition now (`ownerRefersTo` with `anyOf`, the addition a `deletableDocument` lookup); a message only the leader can read; deletable, which withdraws it; the leader acts on it by deleting the addition or removing an elected member |
|
|
102
|
+
|
|
103
|
+
Each exists at most once per member and charter (unique indexes). The team
|
|
104
|
+
that acts is the leader plus the elected members less the removals, plus the
|
|
105
|
+
additions (`ElectedCharter::active_members` in `rs-dpp`).
|
|
106
|
+
|
|
107
|
+
See [the protocol guide](../../docs/protocol/moderation-charters.md) for
|
|
108
|
+
details.
|
|
109
|
+
|
|
110
|
+
## Install
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
npm install @dashevo/moderation-charters-contract
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
[MIT](LICENSE) © Dash Core Group, Inc.
|
package/lib/systemIds.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dashevo/moderation-charters-contract",
|
|
3
|
+
"version": "4.2.0-beta.4",
|
|
4
|
+
"description": "A system contract for the charters of elected moderation teams",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"lint": "eslint .",
|
|
7
|
+
"test": "yarn run test:unit",
|
|
8
|
+
"test:unit": "mocha 'test/unit/**/*.spec.js'"
|
|
9
|
+
},
|
|
10
|
+
"contributors": [
|
|
11
|
+
{
|
|
12
|
+
"name": "Samuel Westrich",
|
|
13
|
+
"email": "sam@dash.org",
|
|
14
|
+
"url": "https://github.com/quantumexplorer"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@dashevo/wasm-dpp": "workspace:*",
|
|
20
|
+
"chai": "^4.3.10",
|
|
21
|
+
"dirty-chai": "^2.0.1",
|
|
22
|
+
"eslint": "^9.18.0",
|
|
23
|
+
"mocha": "^11.1.0",
|
|
24
|
+
"sinon": "^18.0.1",
|
|
25
|
+
"sinon-chai": "^3.7.0"
|
|
26
|
+
}
|
|
27
|
+
}
|