# Implementing GDPR-Compliant Surveys Using Blockchain
## 5 System Implementation
### Code  
This subsection describes the main functions used in the chaincode (CC) and API. All the code used in this project can be found online (REF, accessed on 27 March 2023). The structure presented in Listing 1 is used to hold the metadata of the surveys (ID, description, fields, and deadline) and the CIDs of the files that contain information relative to the survey. type Asset struct {  
ID string 'json:''ID''Description string 'json:''description''Fields string 'json:fields'CIDs string 'json:''cids''Deadline string 'json:''dealine''  
The code present in Listing 2 is used to create a survey. As with other examples below, data validations are not included here for brevity and comprehensibility. The function receives a survey's ID, description, fields, and deadline and creates an asset with an empty array of CIDs. This array will be populated with the CIDs of answers as the users respond to the questionnaires. func (s *SmartContract) CreateSurvey(ctx contractapi. TransactionContextInterface, idstring, descriptionstring, fields string, deadline_strstring) error {  
asset := Asset{  
ID: id, Description, Fields: fields, CIDs: \"\", Deadline: deadline_str, }  
assetJSON, err := json.Marshal(asset)iferr!=nil{ returnerr } returnctx.GetStub().PutState(id,assetJSON) } ```
The code present in Listing 3 is used to read a survey. The function retrieves the asset and parses the data to JSON. The JSON object containing the surveys' metadata and the answers' CIDs is then sent to the API that obtains the IPFS files and presents them to the DC. ``` //ReadAssetreturnstheassetstoredintheworldstatewithgivenid. func(s*SmartContract)ReadSurvey(ctxcontractapi. TransactionContextInterface,idstring)(*Asset,error){ assetJSON,err:=ctx.GetStub().GetState(id) varassetAsset err=json.Unmarshal(assetJSON,&asset) iferr!=nil{ returnnil,err } return&asset,nil } ```
The code presented in Listing 4 is used to delete a file across the IPFS cluster. First, the function removes the CID from the pinset of the cluster (unpin); second, it invokes the garbage collector that removes all the unpinned files (the file that was previously unpinned); and third, the function returns the result of the two operations (unpinning and calling the garbage collector). ``` defdelete(cid): command=''/gopath/bin/ipfs-cluster-ctlpinrm'+str(cid) proc=subprocess.Popen(command,shell=True,stdout=subprocess.PIPE) lines=proc.stdout.readlines() pinned=''pinisnotpartofthenpinset''notinlines[2].decode() #invokesthegarbage collector command=''-/gopath/bin/ipfs-cluster-ctlipfsgc'' proc=subprocess.Popen(command,shell=True,stdout=subprocess.PIPE) lines=proc.stdout.readlines() removed=''-''notinlines[2].decode() ifpinnedandnotremoved: returnTrue else: returnFalse ```
The code presented in Listing 5 is used to remove the survey metadata from the blockchain and the files containing answers relative to that survey. It starts by invoking the read function of surveys in the blockchain. After that, the function iterates over the list of CIDs and deletes each from the IPFS network. When all the IPFS files of that survey have been deleted, the function invokes the HLF to remove the survey metadata from the blockchain. This function can be easily changed to delete only the answers of a survey (the IPFS files), leaving the metadata in the blockchain (ID, description, fields, and deadline) if desirable. Finally, the code presented in Listing 6 is invoked by a continuously running observer to verify if there are any expired surveys and, if so, invokes the function that deletes surveys (see Listing 5). The observer requests the list of surveys from the blockchain and iterates over it, comparing the deadline of each survey with the present time and deletes the survey if it expired. In addition to the chaincode, we have created several methods in the API and web pages to support the surveys, namely a page with the available options for each user and a specific page for each method.