Open Data Trusted Anchors - Project
The description here under gives all the detail on how the SC is destined, how to install it, how to test it.
Introduction
The Open Data Trusted Anchors (ODTA) project is described under Git https://github.com/IPConvergence/TrustedDistributedOpenDataRegistry
Different illustration video has been done to better understand the Project Code Repo:
Javascript Test on solidity code + explanation of the Code Repo structure: https://youtu.be/mPddwMQAbMo
Demonstrator of the end to end Web Demo Application: https://youtu.be/iRPzkw89-WQ
Integration of the ODTA Registry with Multi-sig Wallet: https://youtu.be/o_f6MhY5Gio
Deployment of the ODTA Registry on Rinkeby Testnet: https://youtu.be/-y7qY440Pv4
Data Asset JSON Modeling
Example of a JSON/JSON-LD Data Asset of a CO2 Measure done by a City Sensor
The bruto "dataAssetValue" is:
The Data Producer must enrich that "dataAssetValue" with MetaData and produce a DataAsset Envelop formated in JSON, linked Data in order to be exchanged between Data Producer and Data Consumer as illustrated here under. Each use case will be in charge of formating the "dataAssetValue" according to the model here under.
Some of the MetaData will be anchored on the Open Data Trusted Anchor Smart Contract to enable trusted data exchange as explained in the project Github page.
PropertyName | Property Type | Requ. JSON | Requ. On SC | Description |
Context | String | Optional | No | Semantic Web Context URL if published on a Registry |
Data Asset Domain | String | Optional | Yes | Name of the domain to which is linked the Data Asset |
Data Asset Producer Name | String | Optional | Yes | Name of the Data Asset Producer |
Data Asset Producer ID | String | Mandatory | Yes | Unique Data Producer ID, can be a public key |
Data Asset ID | String | Mandatory | Yes | Unique identifier of the Data Asset, will be the hash of the base64 encoded version of the full JSON |
Data Asset Value | JSON/ String | Mandatory | No | JSON including the Data Asset Content value |
Data Asset Access Type | String | Mandatory | Yes | Type of Access linked to the Data Asset: Free or payable |
Data Asset Access Condition | String | Optional | No | URL pointing to the describing ot the Data Asset Access Conditions, like price and modality if payable |
Data Asset Use & Processing Conditions | String | Optional | No | URL pointing to the describing ot the Data Asset Access Use & Processing Conditions |
Proof Of Integrity Data Asset | String | Mandatory | Yes | Hash of the JSON of the Data Asset |
Proof Of Source Authenticity | String | Mandatory | Yes | Hash of PublicKey of Data Producer |
Proof of Integrity Use & Processing Conditions | String | Mandatory | Yes | Hash of the Data Asset Access Use & Processing Conditions document |
proof | JSON/String | Optional | No | JSON-LD Signature of the Data Producer of the Asset |
Smart Contract Data Modeling
We will define here under the resources that will be created at SmartContract Level to manage the anchoring of the required Data Asset information needed to deliver trust services.
The following resources will be needed:
Data Producer
Data Consumer
Data Asset
In the rest of the document when playing about a KeyValue Map data structure, we will use "KVM" acronym.
Objects: used by Data Administrator of SmartContract
Object | Type | Description |
stopped | bool | Variable used to put on pause a SmartContract by the SC administrator |
owner | address | Address of the SmartContract owner |
operatorSC | address | Address of the Operator of the SC, that can put it in pause mode also |
Objects: used by Data Producer
Object | Type | Description |
dataProducerStore | mapping (address => bytes32[]) | KVM(dataProducerID -> dataProducerDataAssetList) |
dataProducerDataAssetList | bytes32 [] | Array of dataAssetID |
Objects: for managing Data Consumer
Object | Type | Description |
dataAssetConsumerID | address | Unique ID identifying a data consumer. For this project, we will use the Ethereum Address of the user |
Objects: for managing Data Asset
Object | Type | Description |
dataAssetIDList | mapping (bytes32 => bool) | KVM(dataAssetID -> bool) |
dataAssetStore | mapping (bytes32 => dataAssetObject) | KVM (dataAssetID -> dataAssetObject) |
dataAssetObject | struct | { address dataAssetProducerID; accessType dataAssetAccessType; uint256 dataAssetAccessPrice; string dataAssetAccessDuration; bytes32 proofOfIntegrigyDataAsset; bytes32 proofOfSourceAuthenticity; bytes32 proofOfIntegrityUseProcessingConditions; } |
dataAssetAccessStore | mapping (bytes32 => mapping(address => dataAssetAccessObject)) | KVM (dataAssetID -> KVM(dataAssetConsumerID -> dataAssetAccessObject)) |
dataAssetAccessObject | struct | { bool dataAssetAccessStatus; string dataAssetAccessStartDate; string dataAssetAccessEndDate; } |
accessType | enum | {free, paying} |
dataAssetTotal | uint256 | Count the number of Data Asset Anchored on the Registry |
SmartContract Design
In this section, we will define the SC Architecture used. The Registry will be implemented with 3 Smart Contracts:
ODTA Validator Smart Contract -> Main SC logic
ODTA Storage Smart Contract -> Diamond Storage Illustration
ODTA Proxy Smart Contract -> recommand to use Open Zepplin SC (out of scope of this first version of the project)
Gnosis Multi-Sig Smart Contract -> reuse Gnosis Multi-Sig Wallet for operator of SC
Using a Library in ODTAValidator SC
On the ODTAValidator SC, there is a state variable that is counting the number of DataAsset enchored on the ODTA. In order to avoid any overflow, we use a MathSage.sol lib managing it.
Design Pattern
Circuit breaker / Emergency stop pattern
Assembly code demonstrating inside SC
We have define as illustration a Diamond Storage on ODTAStorage.sol
Current ODTA SC - Administration and Upgradability
As the current project focus on setting up an ODTA application specific SC, we have used the design pattern of a Monolithic SC, also to focus on an immutable character of that SC, that could not be upgraded later on to avoid risk of someone manipulating the logic and content of the SC.
If in your application you need upgradability pattern support, meaning keeping a unique SC address for all the file and supporting upgradability of the logic of the SC and also keeping all the existing data anchored inside of it, we recommend then the OpenZepplin Proxy Design Pattern, combined with a Diamond Storage instanciated on the proxy.
Proxy Design Pattern - For Upgradability - Guidelines to support it
We have focus on this project on the creation of the ODTA application specific SmartContract. If you want to support upgradability of the SC without changing the address of the SC, we recommand you to use the OpenZepplin Proxy component implementation. Please refer to the https://github.com/OpenZeppelin/openzeppelin-sdk/tree/master/packages/lib/contracts/upgradeability
The idea is that you communicate to the public consumers the address of the OpenZepplin deployed Proxy SC for your ODTA. Then on The OpenZepplin Proxy ODTA SC, you point to the address of the ODTA SC referenced in this project. In order to support full upgradability, meaning that anytime you upgrade the ODTA SC implementation of a specific version, you don't loose the data, you need to define on the Proxy SC all the Diamond Storage for all the data objects used on the ODTA implementation. To give you an example, we have implemented on the ODTA project here one ODTAStorage.sol SC defining a DiamondStorage. We defined in the ODTAStorave.sol a "struct" that contain the version number of the SC. You should need to place in that struct all the other objects used on the ODTAValidator to support this full upgradability.
Using Multi-Sig Wallet for Operator on the ODTA
We recommand to use the Gnosis MultiSig SC to define a MultiSig Wallet for the operator of the ODTA SC. Please use the tool https://wallet.gnosis.pm/, simply connect your Meta Mask to your Web3ServiceProvider (so to your target Ledger), define a multisig SC and deploy it.
Go to http://wallet.gnosis.pm -> go in wallets section and select add on the top rigth. Setup the following parameters:
Name: Name of your multisig wallet, to remind it on Gnosis UI
Required confirmations: number of signature requested minimum in the group
Owners: add all the ethereum addresss you want as part of the multi sig.
Then click Deploy -> it will deploy on the Web3 providers you have configured on you metamask
The you have to set the address of the multisig wallet as the operator of the ODTA SC.
You can use a simple test Javascript to do it
Then still from gnosis UI URL link here above perform transaction to the ODTA SC Address by selecting the ABI method setSCVersion() from the multisig, after having setup via the method setOperator from the owner adress the mutlisig wallet address.
Setup the following field on the Gnosis multi-sig wallet to make the transaction.
You need to make the operation here under, from an account on you metamask that you have selected as member of the multisig wallet you have created on Gnosis. If you have setup X signature request on the multi-sig, you need to perform the operation here under from each account, so don't forget to select the good account on your MetaMask wallet, each time you interact with your multisig via the Gnosis UI.
Destination: Put the address where you have deployed your ODTA SC
Contract Name: option name for Gnosis, so that he can remind it
Amount Eth: you can let default
ABI String: copy past from you .buidl/ODTAValidator.json the signature of the setSCVersion() Method
Method: if you put correctly the ABI of the method, you can scroll and should automatically see the method: "setSCVersion()" Method. Select it
Insert in the version parameter thet value: 4
The click on Send multisig transaction
Change Gaz price to 20
Click Send Transaction
Your Metamask client will popup to ask you to sign the transaction that you post to your multi sig wallet. In our case, this is a metamask account that is part of the multisig that will sign a transaction send to the multiSig Gnosis SC we have deployed on ganache. Then the mutlisig SC will send a transaction from the mutlisig Address to the ODTA SC and invoke the setSCVersion() function.
Then you will see on your Gnosis UI, and validate that the transaction has been executed. In the executed column of the transaction, you should see "Executed"
We can test then if the value of the SC version parameter has been well changed by the multisig wallet:
Run the following test script under ./project/test -> This will try to insert a content on the ODTA Registry SC
Launch on your CLI: $: truffle test
It will launch the execution of you js present in your ./project/test folder
See video as illustration on ODTA integration with Gnosis MultiSig Wallet https://youtu.be/o_f6MhY5Gio, the demo has been done with my local ganache-cli
Just as info, if you want to understand the UI code:https://github.com/gnosis/MultiSigWallet/tree/master/dapp,
Testing Code Security/Quality
The Code of ODTAValidator.sol has been tested with MythX (https://mythx.io)
First install the MythX security plugin for Truffle Framework
Then run the Test of your smartcontract code
You can validate the result in your dashboard on Mythx
There is a Javascript code that has been done to test the functionalities of the SC. This is under "/Project/Test/Test_ODTAValidator.js
The video demonstrating the good result of the test is on: https://youtu.be/mPddwMQAbMo
Integration with IPFS (In Option)
As as complementary to the present project project, please read on https://github.com/IPConvergence/ipfs-eth-anchoring
There is a sample demonstrator that enables to anchor on IPFS any input documents. This can be used in complementary to this ODTA application to store any Data Asset JSON File on IPFS and have the hash value of it. Then this hash value can be anchored on the ODTA Registry which is the focus of the present project.
!!! Don't consider the SC part of this IPFS demonstrator, this is not part of this project.
You can test the demonstrator (not garantee to be up all the time, this is test env, no SLA): http://blockchainbeta.eu:3000/
You can upload Data Asset in json format on it. The template is on ./project/src/templateDataAsset.json
The demonstrator on blockchaineu here above is also anchoring the hash of the JSON file on a SC (This SC is not linked with the ODTA SC of this project, it is just for illustration).
For the illustration othe Data Asset here above is stored on IPS on :https://ipfs.io/ipfs/QmdHuLGizKRU3o4TMUByXP3JdvEHUSBKyXUGd4nbJh98Uh
His Hash value is: QmdHuLGizKRU3o4TMUByXP3JdvEHUSBKyXUGd4nbJh98Uh
You can use that hash value as input to the ODTA SC (convert it on Bytes32 before)
Here under is a illustration of the storage on the IPFS of the Data Asset here above
SmartContract Methods
In this section, we will define for each SC, the signature of each method defined in it.
Function | Input | Output |
insertDataAsset | (address _dataAssetProducerID, string _dataAssetAccessType, uint256 _dataAssetAccessPrice, string _dataAssetAccessDuration, bytes32 _proofOfIntegrigyDataAsset, bytes32 _proofOfSourceAuthenticity, bytes32 _proofOfIntegrityUse&ProcessingConditions ) | |
getDataAsset | (bytes32 _dataAssetID) | (address _dataAssetProducerID, accessType _dataAssetAccessType, string _dataAssetAccessPrice, string _dataAssetAccessDuration, bytes32 _proofOfIntegrigyDataAsset, bytes32 _proofOfSourceAuthenticity, bytes32 _proofOfIntegrityUse&ProcessingCondictions ) + generate eventGetDataAccess (address _dataAssetProducerID, address _dataAssetConsumerID, bytes32 _dataAssetID) |
getDataAssetAccessType | (bytes32 _dataAssetID) | (accessType _dataAssetAccessType) |
insertDataAssetAccess | (bytes32 _dataAssetID, address _dataAssetConsumerID) | |
getDataAssetAccess | (bytes32 _dataAssetID, address _dataAssetConsumerID) | (bool _access) |
getDataAssetTotal | () | (uint256 _dataAssetTotal) |
payToAccessDataAsset | (bytes32 _dataAssetID, address payable _toDestination) | Not yet implemented in version v1.0 |
toggleContractActive | () | Circuit Breaker-Pause that can only be called by the owner or operator of the SC. It put all the method on pause if invoked. |
setOperator | (address _operatorSC) | Function called by SC owner to setup an operator of it (to call Circuit Breaker-Pause) |
getOperator | () | (address _operatorSC), return address of operator of the SC |
setSCVersion | (uint256 version) | Set the SC version number on a Diamond storage |
getSCVersion | () | (uint256) return the SC version number on Diamond storage |
Front-End Demo Web Server
Here under we explain the Front-End Demo Web Server we implement to show a demonstrator Consumer Wep Application to interact with the ODTA SmartContract.
If you want to use Local Ganache Deployed SC from the Web FE:
Go to ProjectFolder/src/js
the app.js is by default using the deployed Version on ganache
If you want to use the Rinkeby deployed SC from the WE FE
Go to ProjectFolder/src/js
rename "app.js" to app_backup.js"
rename "app-if-RinkebySC.js" -> to "app.js"
You will see that the difference between the 2 js files is that one is using the "deploy() method on the truffle SC object, while the other is using the at("ODTA_AddressOn-Rinkeby").
Demo Video
The Demo of the Frond-End Application is on : https://youtu.be/iRPzkw89-WQ
We will use the npm lite Server. Setup instruction are on https://www.npmjs.com/package/lite-server
We have setup for demo the Front End Demonstrator on a server, that you can use to test it:
Deploy ODTA SC
Deploy ODTA SC on Local Ganache Network
Step1: Launch Ganache CLI Locally
Step2: Launch Chrome and go to Metamask, enter the mnemonic coming from the ganache-cli accounts, to have Metamask connected to the local blockchain (the ganache version)
Step 3: Edit your truffle-config.js to indicate to truffle where is the ledger you use
Step3: run on CLI the compilation and deployement of SmartContract
When you run truffle migrate, if will look at the /migrations folder for the js file. Don't forget to edit the "1_initial_migration.js" & "2_deploy_contracts.js" to point to your solidity contracts (Migration.sol and ODTAValidator.sol)
Deploy ODTA SC on Rinkeby Public Ethereum Test Network
The deployment of the ODTA SC of the Rinkeby Network will be done via the Infura Web Gateway to the Rinkeby network, to avoid to install locally a Ethereum Get client connected to Rinkeby.
Step1: Install on the project directory, the JS NPM component wallet that will enable to use a software javascript component for olding the keys of the Rinkeby account you will use to deploy the SC
Step2: Go to your MetaMask client connected to Rinkeby and copy the mnemonic of your Rinkeby account. Then save your param mnemonic in .secret in the project home directory. !! Do not do this on production with real value, this is for simulation lab only
Step3: To perform transaction on Rinkeby, we need some Ether. Get free Rinkeby ether by going to this website
Step4: To deploy contracts to the testnet using Truffle without having to sync a local node, you can use Infura. Infura allows you to access a fully synced Ethereum node via their API. We will use their API to deploy our contracts to the Rinkeby testnet. Go to the Infura website and sign up for a free account.Create there a project and copy the API Access key
Step5: update your truffle-config.js file
Step6: Deploy your ODTA SC on Rinkeby Network
The ODTA Contract is deployed on Rinkeby at the following address: 0x45b9d883aB05b081015E67e031516379f2C148D8
Deployment of the ODTA Registry on Rinkeby Testnet: https://youtu.be/-y7qY440Pv4
A transaction has been posted by my account (0x7c584e710fe6afa5369a8bffee47fc98d76535a5) to authorize access to Atmospheric Pressure Measure 4 Data Asset of the demonstrator to everyone, as free asset.
The transaction proof is on Rinkeby Etherscan: https://rinkeby.etherscan.io/tx/0xb25d36e4475f05a3cf76f90dad0100a980b12ede45713544f20d89810f33debc
If you connect you metamask to Rinkeby and run the WebDemonstrator of ODTA from your local PC on localhost:8000, you will see that you have access right authorized to the Atmospheric Pressure Mesure 4 Data Asset
You can also connect to the http://blockchainbeta.eu/ with your MetaMask on Rinkeby. But you will have access only ot the Atmospheric Pressure Measure 4 Data Asset of the demonstrator, as the "dataAssets.json" hosted on the Demo Web service on this URL is controlled by me.
So to really use the SC on Rinkeby and insert content, you should deploy the NPM Web server part of the ODTA project and run it on your Web server, then you need to replace the "app.js" file on project/scr/js to "app-UsingRinkebySC" that is pointing to the Rinkeby SC ODTAValidator.sol
Last updated