@@ -2,111 +2,201 @@ pragma solidity ^0.6.4;
2
2
pragma experimental ABIEncoderV2;
3
3
4
4
import "./Governed.sol " ;
5
+ import "./erc1056/IEthereumDIDRegistry.sol " ;
5
6
6
7
/**
7
8
* @title GNS
8
9
* @dev The Graph Name System contract provides a decentralized namings system for subgraphs
9
- * used in the scope of the Graph Network. It translate subgraph names into
10
- * subgraphDeploymentID regarded as versions.
10
+ * used in the scope of the Graph Network. It translates subgraph names into subgraph versions.
11
+ * Each version is associated with a Subgraph Deployment. The contract no knowledge of human
12
+ * readable names. All human readable names emitted in events.
11
13
*/
12
14
contract GNS is Governed {
13
- // -- Types --
14
-
15
- enum RecordType { GNS }
15
+ // -- State --
16
16
17
- struct Record {
18
- address owner;
19
- bytes32 subgraphDeploymentID;
20
- RecordType nameSystem;
21
- }
17
+ // graphAccountID => subgraphNumber => subgraphDeploymentID
18
+ // graphAccountID = An ERC-1056 ID
19
+ // subgraphNumber = Simply a number associated to a graph accounts deployed subgraph. This
20
+ // is used to create a subgraphID (graphAccountID + subgraphNumber)
21
+ // subgraphDeploymentID = The IPFS hash of the manifest of the subgraph
22
+ mapping (address => mapping (uint256 => bytes32 )) public subgraphs;
22
23
23
- // -- State --
24
+ // graphAccount => a counter of the accounts subgraph deployments
25
+ mapping (address => uint256 ) public graphAccountSubgraphNumbers;
24
26
25
- mapping (bytes32 => Record) public records;
27
+ // ERC-1056 contract reference
28
+ IEthereumDIDRegistry public erc1056Registry;
26
29
27
30
// -- Events --
28
31
29
32
/**
30
- * @dev Emitted when `owner` publish a `subgraphDeploymentID` version under subgraph `name`.
31
- * The event also attach `metadataHash` with extra information.
33
+ * @dev Emitted when a `graph account` publishes a `subgraph` with a `version`.
34
+ * Every time this event is emitted, indicates a new version has been created.
35
+ * The event also emits a `metadataHash` with subgraph details and version details.
36
+ * Name data is emitted, as well as the name system.
32
37
*/
33
38
event SubgraphPublished (
34
- string name ,
35
- address owner ,
39
+ address graphAccount ,
40
+ uint256 subgraphNumber ,
36
41
bytes32 subgraphDeploymentID ,
42
+ uint256 nameSystem , // placeholder until we implement more than ENS
43
+ bytes32 nameIdentifier ,
44
+ string name ,
37
45
bytes32 metadataHash
38
46
);
39
47
40
48
/**
41
- * @dev Emitted when subgraph `nameHash` is unpublished by its owner.
49
+ * @dev Emitted when a graph account deprecated one of their subgraphs
42
50
*/
43
- event SubgraphUnpublished ( bytes32 nameHash );
51
+ event SubgraphDeprecated ( address graphAccount , uint256 subgraphNumber );
44
52
45
53
/**
46
- * @dev Emitted when subgraph `nameHash` is transferred to new owner.
47
- */
48
- event SubgraphTransferred ( bytes32 nameHash , address from , address to );
49
-
50
- modifier onlyRecordOwner ( bytes32 _nameHash ) {
51
- require (msg . sender == records[_nameHash].owner , "GNS: Only record owner can call " );
54
+ @dev Modifier that allows a function to be called by owner of a graph account. Only owner can call
55
+ @param _graphAccount Address of the graph account
56
+ */
57
+ modifier onlyGraphAccountOwner ( address _graphAccount ) {
58
+ address graphAccountOwner = erc1056Registry. identityOwner (_graphAccount);
59
+ require (graphAccountOwner == msg . sender , "GNS: Only graph account owner can call " );
52
60
_;
53
61
}
54
62
55
63
/**
56
64
* @dev Contract Constructor.
57
65
* @param _governor Owner address of this contract
66
+ * @param _didRegistry Address of the Ethereum DID registry
58
67
*/
59
- constructor (address _governor ) public Governed (_governor) {}
68
+ constructor (address _governor , address _didRegistry ) public Governed (_governor) {
69
+ erc1056Registry = IEthereumDIDRegistry (_didRegistry);
70
+ }
60
71
61
72
/**
62
- * @dev Publish a version using `subgraphDeploymentID` under a subgraph..
63
- * @param _name Name of the subgraph
64
- * @param _subgraphDeploymentID SubgraphDeployment to link to the subgraph
65
- * @param _metadataHash IPFS hash linked to the metadata
73
+ * @dev Allows a graph account to publish a new subgraph, which means a new subgraph number
74
+ * will be allocated. It then will call publish version. Subsequent versions can be created
75
+ * by calling publishVersion() directly.
76
+ * @param _graphAccount Account that is publishing the subgraph
77
+ * @param _subgraphDeploymentID Subgraph deployment ID of the version, linked to the name
78
+ * @param _nameIdentifier The value used to look up ownership in the naming system
79
+ * @param _name Name of the subgraph, from any valid system
80
+ * @param _metadataHash IPFS hash for the subgraph, and subgraph version metadata
66
81
*/
67
- function publish (
82
+ function publishNewSubgraph (
83
+ address _graphAccount ,
84
+ bytes32 _subgraphDeploymentID ,
85
+ bytes32 _nameIdentifier ,
68
86
string calldata _name ,
87
+ bytes32 _metadataHash
88
+ ) external onlyGraphAccountOwner (_graphAccount) {
89
+ uint256 subgraphNumber = graphAccountSubgraphNumbers[_graphAccount];
90
+ publishVersion (
91
+ _graphAccount,
92
+ subgraphNumber,
93
+ _subgraphDeploymentID,
94
+ _nameIdentifier,
95
+ _name,
96
+ _metadataHash
97
+ );
98
+ graphAccountSubgraphNumbers[_graphAccount]++ ;
99
+ }
100
+
101
+ /**
102
+ * @dev Allows a graph account to publish a subgraph, with a version, a name, and metadata
103
+ * Graph account must be owner on their ERC-1056 identity
104
+ * Graph account must own the name of the name system they are linking to the subgraph
105
+ * Version is derived from the occurance of SubgraphPublish being emitted. i.e. version 0
106
+ * is the first time the event is emitted for the graph account and subgraph number
107
+ * combination.
108
+ * @param _graphAccount Account that is publishing the subgraph
109
+ * @param _subgraphNumber Subgraph number for the account
110
+ * @param _subgraphDeploymentID Subgraph deployment ID of the version, linked to the name
111
+ * @param _nameIdentifier The value used to look up ownership in the naming system
112
+ * @param _name Name of the subgraph, from any valid system
113
+ * @param _metadataHash IPFS hash for the subgraph, and subgraph version metadata
114
+ */
115
+ function publishNewVersion (
116
+ address _graphAccount ,
117
+ uint256 _subgraphNumber ,
69
118
bytes32 _subgraphDeploymentID ,
119
+ bytes32 _nameIdentifier ,
120
+ string calldata _name ,
70
121
bytes32 _metadataHash
71
- ) external {
72
- address owner = msg .sender ;
73
- bytes32 nameHash = keccak256 (bytes (_name));
122
+ ) external onlyGraphAccountOwner (_graphAccount) {
74
123
require (
75
- ! isReserved (nameHash) || records[nameHash].owner == owner,
76
- "GNS: Record reserved, only record owner can publish "
124
+ isPublished (_graphAccount, _subgraphNumber) || // Hasn't been created yet
125
+ _subgraphNumber < graphAccountSubgraphNumbers[_graphAccount], // Was created, but deprecated
126
+ "GNS: Cant publish a version directly for a subgraph that wasnt created yet "
77
127
);
78
128
79
- records[nameHash] = Record (owner, _subgraphDeploymentID, RecordType.GNS);
80
- emit SubgraphPublished (_name, owner, _subgraphDeploymentID, _metadataHash);
129
+ publishVersion (
130
+ _graphAccount,
131
+ _subgraphNumber,
132
+ _subgraphDeploymentID,
133
+ _nameIdentifier,
134
+ _name,
135
+ _metadataHash
136
+ );
81
137
}
82
138
83
139
/**
84
- * @dev Unpublish a subgraph name. Can only be done by the owner.
85
- * @param _nameHash Keccak256 hash of the subgraph name
140
+ * @dev Internal function used by both external publishing functions
141
+ * @param _graphAccount Account that is publishing the subgraph
142
+ * @param _subgraphNumber Subgraph number for the account
143
+ * @param _subgraphDeploymentID Subgraph deployment ID of the version, linked to the name
144
+ * @param _nameIdentifier The value used to look up ownership in the naming system
145
+ * @param _name Name of the subgraph, from any valid system
146
+ * @param _metadataHash IPFS hash for the subgraph, and subgraph version metadata
86
147
*/
87
- function unpublish (bytes32 _nameHash ) external onlyRecordOwner (_nameHash) {
88
- delete records[_nameHash];
89
- emit SubgraphUnpublished (_nameHash);
148
+ function publishVersion (
149
+ address _graphAccount ,
150
+ uint256 _subgraphNumber ,
151
+ bytes32 _subgraphDeploymentID ,
152
+ bytes32 _nameIdentifier ,
153
+ string memory _name ,
154
+ bytes32 _metadataHash
155
+ ) internal {
156
+ require (_subgraphDeploymentID != 0 , "GNS: Cannot set to 0 in publish " );
157
+
158
+ // Stores a subgraph deployment ID, which indicates a version has been created
159
+ subgraphs[_graphAccount][_subgraphNumber] = _subgraphDeploymentID;
160
+ // Emit version and name data
161
+ emit SubgraphPublished (
162
+ _graphAccount,
163
+ _subgraphNumber,
164
+ _subgraphDeploymentID,
165
+ 0 ,
166
+ _nameIdentifier,
167
+ _name,
168
+ _metadataHash
169
+ );
90
170
}
91
171
92
172
/**
93
- * @dev Tranfer the subgraph name to a new owner.
94
- * @param _nameHash Keccak256 hash of the subgraph name
95
- * @param _to Address of the new owner
173
+ * @dev Deprecate a subgraph. Can only be done by the erc-1506 identity owner.
174
+ * @param _graphAccount Account that is publishing the subgraph
175
+ * @param _subgraphNumber Subgraph number for the account
96
176
*/
97
- function transfer (bytes32 _nameHash , address _to ) external onlyRecordOwner (_nameHash) {
98
- require (_to != address (0 ), "GNS: Cannot transfer to empty address " );
99
- require (records[_nameHash].owner != _to, "GNS: Cannot transfer to itself " );
100
- records[_nameHash].owner = _to;
101
- emit SubgraphTransferred (_nameHash, msg .sender , _to);
177
+ function deprecate (address _graphAccount , uint256 _subgraphNumber )
178
+ external
179
+ onlyGraphAccountOwner (_graphAccount)
180
+ {
181
+ require (
182
+ isPublished (_graphAccount, _subgraphNumber),
183
+ "GNS: Cannot deprecate a subgraph which does not exist "
184
+ );
185
+ delete subgraphs[_graphAccount][_subgraphNumber];
186
+ emit SubgraphDeprecated (_graphAccount, _subgraphNumber);
102
187
}
103
188
104
189
/**
105
- * @dev Return whether a subgraph name is registed or not.
106
- * @param _nameHash Keccak256 hash of the subgraph name
107
- * @return Return true if subgraph name exists
190
+ * @dev Return whether a subgraph name is published.
191
+ * @param _graphAccount Account being checked
192
+ * @param _subgraphNumber Subgraph number being checked for publishing
193
+ * @return Return true if subgraph is currently published
108
194
*/
109
- function isReserved (bytes32 _nameHash ) public view returns (bool ) {
110
- return records[_nameHash].owner != address (0 );
195
+ function isPublished (address _graphAccount , uint256 _subgraphNumber )
196
+ public
197
+ view
198
+ returns (bool )
199
+ {
200
+ return subgraphs[_graphAccount][_subgraphNumber] != 0 ;
111
201
}
112
202
}
0 commit comments