## 3 Smart Contract Design
### Data Storage and Retrieval  
The pseudo code for the data storage and retrieval is shown in Algorithm 2. The smart contract maintains a string array called database, a mapping called tagindex, and a counter that remembers the last index to the database, as shown in Figure 7. The tag and the data for each write operation are regarded as opaque objects. How the tag and data are encoded and the relationship between the tag and the data to be written to the contract are completely up to the user. Although we recommend the tag to be limited to 32 bytes to save on gas, we do not impose any limit on the tag length. Furthermore, the tag can be unique among all the writes or it could be the same for multiple writes. To facilitate query of the data written to the smart contract, we offer three functions: (1) fetch all data that carry the same given tag; (2) fetch all data written to the contract; and (3) fetch a given number of most recent data entries written to the contract. If the tag and/or the data are encoded properly, one may conduct various queries on the fetched data.  
To write data to the contract, one would call on the write function with a tag and a data entry (lines 1-12 in Algorithm 2). The data entry is first appended to the database array (line 2 in Algorithm 2), then the tag is added to the tagindex mapping with the current counter as the value (line 3 in Algorithm 2). Finally, the counter is incremented by 1 (line 4 in Algorithm 2).  
Figure 6: Different roles in the user management and user access control and their operations.  
Figure 7: Data structures used for data storing and query operations.  
To fetch data from the contract, one would call the read function with a tag (lines 6-12 in Algorithm 2). The indices array is retrieved from the tagindex mapping (line 7 in Algorithm 2). Then, the entries from the database are retrieved and added into a local result variable in a loop (lines 8-12 in Algorithm 2). Finally, the result is returned to the caller (line 16 in Algorithm 2).  
To fetch all the data written to the contract, one would call the readall function (lines 18-12 in Algorithm 2), where the database is returned to the caller (line 19 in Algorithm 2). The number of entries in the database can be queried via the getdbsize function (lines 21-12 in Algorithm 2). One may fetch the most recent \(n\) entries from the contract via the readrecent function. If \(n\) is the same or larger than the current size of the database, then the entire database is returned to the caller (lines 25-12 in Algorithm 2). Otherwise, the most recent \(n\) entries are retrieved, coped to a local array, and returned to the caller (lines 28-12 in Algorithm 2).  
```
1:mapping(string => uint []) tagindex
2:string [] database
3:uint counter
4:procedurewrite(tag, entry) ONJROLE(W)
5:database.push(entry)
6:tagindex[tag].push(counter)
7:counter++
8:endprocedure
9:procedureread(tag) ONJROLE(R)
10:uint [] indices \(\leftarrow\) tagindex[tag]
11:uint length \(\leftarrow\) indices.length
12:string [] result \(\leftarrow\) new string(length)
13:\(i\gets 0\)
14:while\(i<\) length do
15:entry \(\leftarrow\) database[indices[i]]
16:result[i] \(\leftarrow\) entry
17:\(i++\)
18:endwhile
19:return result
20:endprocedure
21:procedurereadall() ONJROLE(R)
22:return database
23:endprocedure
24:procedurereadpereent(\(n\)) ONJROLE(R)
25:if\(n>=\) counter then
26:return database
27:endif
28:string [] result \(\leftarrow\) new string[](\(n\))
29:\(i\gets 0\)
30:while\(i<n\) do
31:entry \(\leftarrow\) database[counter-i-1]
32:result[i] \(\leftarrow\) entry
33:\(i++\)
34:endwhile
35:return result
36:endprocedure
```  
**Algorithm 2** Algorithm for data write and read.