update to newer version

This commit is contained in:
Josip Milovac 2022-11-24 12:03:27 +11:00
parent d6a32870bc
commit 29138de53e
37 changed files with 15795 additions and 12789 deletions

Binary file not shown.

2
.gitignore vendored
View file

@ -3,6 +3,4 @@
################################################################################ ################################################################################
/.vs /.vs
/.vscode
/node_modules /node_modules
/.metals

13
Notes
View file

@ -1,13 +0,0 @@
npm run dev
PORT=3002 P2P_PORT=5002 PEERS=ws://localhost:5001 npm run dev
PORT=3003 P2P_PORT=5003 PEERS=ws://localhost:5001,ws://localhost:5002 npm run dev
PORT=3004 P2P_PORT=5004 PEERS=ws://localhost:5001,ws://localhost:5002,ws://localhost:5003 npm run dev
PORT=3005 P2P_PORT=5005 PEERS=ws://localhost:5001,ws://localhost:5002,ws://localhost:5003,ws://localhost:5004 npm run dev
.
.
.
.
.
* in this version, on top of adding Mqtt broker to each node and adding new module called integration and integrationVirtual
* we ad blockNum to each block, and we limited the number of transaction for each block

View file

@ -1,47 +0,0 @@
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined

View file

@ -1,92 +0,0 @@
# SenShaMart
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/swinburne-iot-lab/senshamart.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.com/swinburne-iot-lab/senshamart/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

BIN
app/.DS_Store vendored

Binary file not shown.

View file

@ -27,73 +27,53 @@
* to monitor the node * to monitor the node
* *
*/ */
const express = require('express');
const express = require('express'); const bodyParser = require('body-parser');
const bodyParser = require('body-parser'); const Blockchain = require('../blockchain');
const Blockchain = require('../blockchain'); const P2pServer = require('./p2p-server');
const P2pServer = require('./p2p-server'); const Wallet = require('../wallet');
const Wallet = require('../wallet');
const TransactionPool = require('../wallet/transaction-pool'); const TransactionPool = require('../wallet/transaction-pool');
const Miner = require('./miner'); const Miner = require('./miner');
const morgan = require('morgan');//AddedM const QueryEngine = require('@comunica/query-sparql').QueryEngine;
const multer = require('multer');
//const productRoutes = require("./products");//addedM
const newEngine = require('@comunica/actor-init-sparql').newEngine;
const N3 = require('n3'); const N3 = require('n3');
const jsonld = require('jsonld'); const jsonld = require('jsonld');
const DataFactory = require('n3').DataFactory; const DataFactory = require('n3').DataFactory;
const fs = require('fs');
const swaggerUi = require('swagger-ui-express')
const swaggerFile = require('./swagger_output.json')
var lodash = require('lodash');
var mqtt = require('mqtt'); var mqtt = require('mqtt');
var aedes = require('aedes')(); var aedes = require('aedes')(); /* aedes is a stream-based MQTT broker */
var MQTTserver = require('net').createServer(aedes.handle); var MQTTserver = require('net').createServer(aedes.handle);
var mosca = require('mosca'); const fs = require('fs'); /* file system (fs) module allows you to work with
//var awsIot = require('aws-iot-device-sdk'); the file system on your computer*/
'use strict';// "use strict" is to indicate that the code should be executed in "strict mode". const multer = require('multer');/* Multer is a node.js middleware for handling multipart/form-data
// With strict mode, you can not, for example, use undeclared variables. , which is primarily used for uploading files.*/
'use strict';/* "use strict" is to indicate that the code should be executed in "strict mode".
With strict mode, you can not, for example, use undeclared variables.*/
const app = express();
const bc = new Blockchain();
const wallet = new Wallet();
const tp = new TransactionPool();
const p2pServer = new P2pServer(bc, tp);
const miner = new Miner(bc, tp, wallet, p2pServer);
const parser = new N3.Parser({format: 'application/n-quads'}); const parser = new N3.Parser({format: 'application/n-quads'});
const store = new N3.Store(); const store = new N3.Store();
const store2 = new N3.Store(); const myEngine = new QueryEngine();
const myEngine = newEngine();
const app = express();
const bc = new Blockchain();
const wallet = new Wallet();
const tp = new TransactionPool();
const p2pServer = new P2pServer(bc, tp);
const miner = new Miner(bc, tp, wallet, p2pServer);
//var client = mqtt.connect('mqtt://broker.hivemq.com'); app.use(bodyParser.json());
var MOSCAsettings = { MOSCAport:1883 } //initialising a local storage for storing metadata file initially before storing it in the tripple store
//var MOSCAserver = new mosca.Server(MOSCAsettings);
//Mosca mqtt server intialization
// MOSCAserver.on('ready', function(){
// console.log("ready");
// });
//aedes mqtt server intialization
const MQTTport = process.env.MQTT_PORT || 1883;
MQTTserver.listen(MQTTport, function () {
console.log('MQTTserver listening on port', MQTTport)
})
//
const storage = multer.diskStorage({ const storage = multer.diskStorage({
destination: function(req, file, cb) { destination: function(req, file, cb) {
cb(null, './uploads/'); cb(null, './uploads/');
}, },
filename: function(req, file, cb) { filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname); cb(null, new Date().toISOString() + file.originalname);
} }
}); });
//filtering the type of uploaded Metadata files
//filtering the type of uploaded files const fileFilter = (req, file, cb) => {
const fileFilter = (req, file, cb) => {
// reject a file // reject a file
if (file.mimetype === 'application/json' || file.mimetype === 'text/plain' ) { if (file.mimetype === 'application/json' || file.mimetype === 'text/plain' ) {
cb(null, true); cb(null, true);
@ -101,7 +81,7 @@ const fileFilter = (req, file, cb) => {
cb(null, false); cb(null, false);
} }
}; };
// defining a storage and setup limits for storing metadata file initially before storing it in the tripple store
const upload = multer({ const upload = multer({
storage: storage, storage: storage,
limits: { limits: {
@ -110,89 +90,54 @@ const upload = multer({
fileFilter: fileFilter fileFilter: fileFilter
}); });
const port = process.env.HTTP_PORT || 3001; // innitialising the HTTP PORT to listen
const port = process.env.HTTP_PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}`)); app.listen(port, () => console.log(`Listening on port ${port}`));
p2pServer.listen(); p2pServer.listen();
app.use('/doc', swaggerUi.serve, swaggerUi.setup(swaggerFile)) //aedes mqtt server intialization
const MQTTport = process.env.MQTT_PORT || 1882;
MQTTserver.listen(MQTTport, function () {
console.log('MQTTserver listening on port', MQTTport)
})
function log(message) { app.use('/uploads', express.static('uploads')); // to store uploaded metadata to '/uploads' folder
console.log(`New block added: ${message.toString()}`); app.use(bodyParser.json()); //
// fs.writeFileSync('./blocks.json', JSON.stringify(message),{'flags': 'a'}); //the problem with this function was overwrite even when i changed the flag to 'a'
// fs.appendFile('./blocks.json', JSON.stringify(message) ,function(err){ //this function makes erorrs when the data is big
// if(err) throw err;
// console.log('IS WRITTEN')
// });
var BlockStream = fs.createWriteStream("blocks.json", {flags:'a'});
BlockStream.write(message+ "\n");
}
function logQuery(message) { // GET APIs
//console.log(`New block added: ${message.toString()}`);
// fs.writeFileSync('./blocks.json', JSON.stringify(message),{'flags': 'a'}); //the problem with this function was overwrite even when i changed the flag to 'a'
// fs.appendFile('./blocks.json', JSON.stringify(message) ,function(err){ //this function makes erorrs when the data is big
// if(err) throw err;
// console.log('IS WRITTEN')
// });
var QueryStream = fs.createWriteStream("Query.json", {flags:'a'});
QueryStream.write(message+ "\n");
}
///////////////////////////////
app.use(morgan("dev"));//AddedM
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({ extended: false }));//addedM
app.use(bodyParser.json());
//addedM
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
return res.status(200).json({});
}
next();
});
//finished AddedM
//GET functions
app.get('/blocks', (req, res) => { app.get('/blocks', (req, res) => {
res.json(bc.chain); res.json(bc.chain);
}); });
///////////////
app.get('/MetaDataTransactions', (req, res) => { app.get('/MetaDataTransactions', (req, res) => {
res.json(tp.metaDataTransactions); res.json(tp.metadataS);
}); });
///////////////
app.get('/CoinTransactions', (req, res) => { app.get('/PaymentTransactions', (req, res) => {
res.json(tp.cointransactions); res.json(tp.transactions);
}); });
///////////////
app.get('/Transactions', (req, res) => { app.get('/Transactions', (req, res) => {
res.json(tp); res.json(tp);
}); });
///////////////
app.get('/mine-transactions', (req, res) => { app.get('/mine-transactions', (req, res) => {
const block = miner.mine(); const block = miner.mine();
console.log(`New block added: ${block.toString()}`); console.log(`New block added: ${block.toString()}`);
//res.redirect('/blocks'); //res.redirect('/blocks');
res.json("Block mined"); res.json("Block mined");
}); });
///////////////
app.get('/public-key', (req, res) => { app.get('/public-key', (req, res) => {
res.json({ publicKey: wallet.publicKey }); res.json({ publicKey: wallet.publicKey });
}); });
///////////////
app.get('/Balance', (req, res) => { app.get('/Balance', (req, res) => {
res.json({ Balance: wallet.balance }); res.json({ Balance: wallet.balance });
}); });
/////////////////////////////
//POST functions //////////////////////////////////////////////////
// POST APIs
app.post('/mine', (req, res) => { app.post('/mine', (req, res) => {
const block = bc.addBlock(req.body.data); const block = bc.addBlock(req.body.data);
console.log(`New block added: ${block.toString()}`); console.log(`New block added: ${block.toString()}`);
@ -200,9 +145,16 @@ app.post('/mine', (req, res) => {
p2pServer.syncChains(); p2pServer.syncChains();
res.redirect('/blocks'); res.redirect('/blocks');
});
///////////////
app.post('/transact', (req, res) => {
const { recipient, amount } = req.body;
const transaction = wallet.createTransaction(recipient, amount, bc, tp);
p2pServer.broadcastTransaction(transaction);
res.redirect('/transactions');
}); });
///////////////
app.post('/RegistringIoTdevice', (req, res)=> { app.post('/IoTdeviceRegistration', (req, res)=> {
const {Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, const {Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail,
OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte,
PaymentPerMinute,Protocol, MessageAttributes, Interval, PaymentPerMinute,Protocol, MessageAttributes, Interval,
@ -227,7 +179,7 @@ app.post('/RegistringIoTdevice', (req, res)=> {
let MessageAttributesIn = MessageAttributes; let MessageAttributesIn = MessageAttributes;
let IntervalIn = Interval; let IntervalIn = Interval;
let FurtherDetailsIn = FurtherDetails; let FurtherDetailsIn = FurtherDetails;
var metaDataTransaction = wallet.createMetaDataTransaction(NameIn, var metaDataTransaction = wallet.createMetadata(NameIn,
GeoIn, IP_URLIn,Topic_TokenIn, GeoIn, IP_URLIn,Topic_TokenIn,
PermissionIn, RequestDetailIn, OrgOwnerIn, PermissionIn, RequestDetailIn, OrgOwnerIn,
DepOwnerIn, PrsnOwnerIn, PaymentPerKbyteIn, DepOwnerIn, PrsnOwnerIn, PaymentPerKbyteIn,
@ -235,30 +187,30 @@ app.post('/RegistringIoTdevice', (req, res)=> {
MessageAttributesIn, IntervalIn, MessageAttributesIn, IntervalIn,
FurtherDetailsIn, FurtherDetailsIn,
SSNmetadata, tp); SSNmetadata, tp);
p2pServer.broadcastMetaDataTransaction(metaDataTransaction);});
res.json("MetadataTransactionCreated");});
/** /**
* the following piece of code * the following piece of code
* is for storing the metadata as a Nquad format inside the blockchain * is for storing the metadata as a Nquad format inside the blockchain
*/ */
// jsonld.toRDF(metaDataTransaction.SSNmetadata, {format: 'application/n-quads'}, jsonld.toRDF(metaDataTransaction.SSNmetadata, {format: 'application/n-quads'},
// (err, nquads) => { (err, nquads) => {
// // nquads is a string of N-Quads // nquads is a string of N-Quads
// parser.parse( parser.parse(
// nquads, nquads,
// (error, quadN, prefixes) => { (error, quadN, prefixes) => {
// // console.log(quadN) // console.log(quadN)
// if (quadN) if (quadN)
// //console.log(quadN.predicate) //console.log(quadN.predicate)
// store.addQuad(DataFactory.quad( store.addQuad(DataFactory.quad(
// DataFactory.namedNode(quadN.subject.id), DataFactory.namedNode(quadN.subject.id),
// DataFactory.namedNode(quadN.predicate.id), DataFactory.namedNode(quadN.predicate.id),
// DataFactory.namedNode(quadN.object.id))); DataFactory.namedNode(quadN.object.id)));
// }); });
// }); });
// metaDataTransaction.SSNmetadata= store; metaDataTransaction.SSNmetadata= store;
p2pServer.broadcastMetadata(metaDataTransaction);});
res.json("MetadataTransactionCreated");});
///////////////
app.post('/IoTdevicePaymentTransaction', (req, res) => { app.post('/IoTdevicePaymentTransaction', (req, res) => {
const { Recipient_payment_address, Amount_of_money, Payment_method, const { Recipient_payment_address, Amount_of_money, Payment_method,
Further_details} = req.body; Further_details} = req.body;
@ -275,78 +227,54 @@ app.post('/IoTdevicePaymentTransaction', (req, res) => {
res.redirect('/PayPalTransaction') res.redirect('/PayPalTransaction')
} }
}); });
///////////////
app.post("/UploadMetafile", upload.single('file'), (req, res) => { app.post("/UploadMetafile", upload.single('file'), (req, res) => {
// recipient: req.body.recipient, // recipient: req.body.recipient,
// amount : req.body.amount, // amount : req.body.amount,
// const Geo = req.body.Geo; // const Geo = req.body.Geo;
// const IPSO = req.body.IPSO; // const IPSO = req.body.IPSO;
// const Type = req.body.Type; // const Type = req.body.Type;
// const Permission = req.body.Permission; // const Permission = req.body.Permission;
// const OrgOwner = req.body.OrgOwner; // const OrgOwner = req.body.OrgOwner;
const file = req.file; const file = req.file;
//file : req.body.file //file : req.body.file
res.status(201).json({ res.status(201).json({
message: 'Uploading Metadata was successful', message: 'Uploading Metadata was successful',
MetadataFile : file MetadataFile : file
});
}); });
//////simple search engine
app.post('/selectedMeta', (req, res) => {
const {Name}= req.body;
data =bc.chain.map (a => a.data);
var PickedSensors = [];
for (let i= 1; i<data.length; i++ ){
//var pickeditems = [null];
var metadata= data[i][1];
//pickeditems.push(...metadata);
// }
// return meta_array.Geo === 30;
//meta_array=bc.chain.map(b => b.input);
var picked = lodash.find(metadata, x=> x.Name === Name);
if (picked != null){
PickedSensors.push(picked);
}
}
res.json(PickedSensors);
}); });
/////////////////////
//Start of comunica sparql query code //Start of comunica sparql query code
/** /**
* this code under construction * this code under construction
* try Comunica SPARQL RDFJS * try Comunica SPARQL RDFJS
* I believe we need to change the way of storing the metadata * I believe we need to change the way of storing the metadata
*/ */
app.post('/sparql', (req, res) => { app.post('/sparql', (req, res) => {
const {Select,subject,predicate,object,Limit}= req.body; /**these const {Select,subject,predicate,object,Limit}= req.body; /**these
variable are used for the sparql query*/ variable are used for the sparql query*/
var meta = []//represents the array of all metadata inside blockchain var meta = []//represents the array of all metadata inside blockchain
var queryResult var queryResult
BlockData =bc.chain.map (a => a.data); /** extracting the data section // BlockData =bc.chain.map (a => a.data); /** extracting the data section
from each block inside the whole blockchain */ // from each block inside the whole blockchain */
var i;//i represents the number of blocks inside the whole blockchain // var i;//i represents the number of blocks inside the whole blockchain
for ( i= 1; i < BlockData.length; i++ ){ // for ( i= 1; i < BlockData.length; i++ ){
var j //represents number of metadata transaction inside each block // var j //represents number of metadata transaction inside each block
for ( j= 0; j<BlockData[i][1].length ;j++){ // for ( j= 0; j<BlockData[i][1].length ;j++){
meta.push(BlockData[i][1][j]["SSNmetadata"]); } } // meta.push(BlockData[i][1][j]["SSNmetadata"]); } }
parser.parse( // parser.parse(
nquads, // nquads,
(error, quadN, prefixes) => { // (error, quadN, prefixes) => {
if (quadN) // if (quadN)
store.addQuad(DataFactory.quad( // store.addQuad(DataFactory.quad(
DataFactory.namedNode(quadN.subject.id), // DataFactory.namedNode(quadN.subject.id),
DataFactory.namedNode(quadN.predicate.id), // DataFactory.namedNode(quadN.predicate.id),
DataFactory.namedNode(quadN.object.id))); // DataFactory.namedNode(quadN.object.id)));
else {(console.log("no metadata")) // else {(console.log("no metadata"))
store.addQuad(DataFactory.quad( // store.addQuad(DataFactory.quad(
DataFactory.namedNode('http://ex.org/null'), // DataFactory.namedNode('http://ex.org/null'),
DataFactory.namedNode('http://ex.org/null'), // DataFactory.namedNode('http://ex.org/null'),
DataFactory.namedNode('http://ex.org/null')));}}); // DataFactory.namedNode('http://ex.org/null')));}});
const start = async function (a,b){ const start = async function (a,b){
const result = await myEngine.query(`SELECT ${Select} WHERE const result = await myEngine.query(`SELECT ${Select} WHERE
{${subject} ${predicate} ${object}} LIMIT {${subject} ${predicate} ${object}} LIMIT
@ -356,195 +284,10 @@ app.post('/sparql', (req, res) => {
console.log(data.toObject())); console.log(data.toObject()));
queryResult= result.bindingsStream}; queryResult= result.bindingsStream};
start() start()
logQuery(queryResult); // logQuery(queryResult);
res.json(queryResult);}); res.json(queryResult);});
///////////////////////////////////////////////////////////Integration///////////////////////////////////////////////////////////
// this code to query the nquad data straight forward from the blockchain without changing the formt
app.post('/sparql2', (req, res) => {
//find a way to define default values for the comming variables
const {Select,subject,predicate,object,Limit}= req.body; // these variable are used for the sparql query
var meta = [] // represents the array of all metadata inside the blockchain
var queryResult
/**
* change the following code to custome map function to remove the for loop
* and make the code faster
*/
BlockData =bc.chain.map (a => a.data); //extracting the data section from each block inside the whole blockchain
var i;//i represents the number of blocks inside the whole blockchain
for ( i= 1; i < BlockData.length; i++ ){ /**the purpose of this for loop is passing each BlockData to check for metadata
this loop could be avoided if we used custome map function */
var j // j represents the number of metadata transaction inside each block
for ( j= 0; j<BlockData[i][1].length ;j++){ /** the purpose of this for loop is passing each metadata transaction inside each block
this loop could be avoided if we used custome map function */
meta.push(BlockData[i][1][j]["SSNmetadata"]); /**this array depends on the structure of the data section from chain from bc
i represents the number of blocks inside the whole blockchain
j represents the number of metadarta transaction inside each block */
}
}
console.log(meta) // printing the metadata just for testing purposes
// jsonld.toRDF(meta, {format: 'application/n-quads'}, (err, nquads) => { /**
// parser.parse( /**this piece of code is used for parse the metadata and store it in N3store */
// nquads,
// (error, quadN, prefixes) => {
// // console.log(quadN)
// if (quadN)
// store2.addQuad(DataFactory.quad(
// DataFactory.namedNode(meta.subject.id), DataFactory.namedNode(meta.predicate.id), DataFactory.namedNode(meta.object.id)));
// // console.log(store)
// });
// const start = async function (a,b){ // we need this line of code to allow "await" function to work because it requires async function
// const result = await myEngine.query(`SELECT ${Select} WHERE {${subject} ${predicate} ${object}} LIMIT ${Limit}`,
// { sources: [{ type: 'rdfjsSource', value: meta}] })
// result.bindingsStream.on('data', (data) => console.log(data.toObject()));
// queryResult= result.bindingsStream
// // console.log(queryResult)
// };
// start()
// res.json(queryResult);
});
//try to make it return the query results insted of the metadata
//});
/**
* this part is an implementation for sparql-engine
* any line code will be added for this reason will have a comment of "sparql-engne"
*
*/
// const {Parser, Store }=require('n3');
// const {Graph, HashMapDataset, PlanBuilder}= require('sparql-engine');//sparql-engine related
// const CustomGraph =require(/*import your Grapg subclass */);
// // Format a triple pattern acccording to N3 API
// // SPARQL variables must be replaced by `null` values
// function formatTriplePattern (triple){
// let subject = null
// let predicate = null
// let object = null
// if (!triple.subject.startWith('?')){
// subject = triple.subject
// }
// if (!triple.predicate.startWith('?')){
// predicate = triple.predicate
// }
// if(!triple.object.startWith('?')){
// object = triple.object
// }
// return { subject, predicate, object}
// }
//////////////////////END OF SPARQL_ENGINE CODE
// ////////////////sparqle-engine code startred/////////
// /**
// * the following code is for checking sparql-engine
// */
// // class CustomGraph extends Graph {
// // /**
// // * Returns an iterator that finds RDF triples matching a triple pattern in the graph.
// // * @param triple - Triple pattern to find
// // * @return An observable which finds RDF triples matching a triple pattern
// // */
// // find (triple:TripleObject, options: Object): Observable<TripleObject> {/* */}
// // }
// class N3Graph extends Graph {
// constructor (){
// super()
// this._store = store()
// }
// insert (triple){
// return new Promise((resolve, reject) => {
// try {
// this._store.addTriple(triple.subject, triple.predicate, triple.object)
// resolve()
// } catch (e) {
// reject (e)
// }
// })
// }
// find (triple) {
// const {subject, predicate, object}= formatTriplePattern(triple)
// return this._store.getTriple (subject, predicate, object)
// }
// estimateCardinality (triple){
// const {subject,predicate,object} = formatTriplePattern(triple)
// return Promise.resolve(this._store.countTriples(subject,predicate,object))
// }
// }
// const graph = new N3Graph()
// const dataset = new HashMapDataset ('http://example.org#default', graph)
// //load some RDF data into the graph
// const parser = new Parser()
// parser.parse(`
// @prefix foaf: <http://xmlns.com/foaf/0.1/> .
// @prefic : <http://example.org#> .
// :a foaf:name "a" .
// :b foaf:name "b" .
// `).forEach(t => {graph._store.addTriple(t)
// })
// // const GRAPH_A_IRI ='http://example.org#graph-a';
// // const GRAPH_B_IRI ='http://example.org#graph-b';
// // const graph_a =new CustomGraph(/* */);
// // const graph_b = new CustomGraph(/* */);
// // //we set graph_a as a defualt RDF dataset
// // const dataset = new HashMapDataset(GRAPH_A_IRI, graph_a);
// // //insert graph_b as a Named Grapg
// // dataset.addNamedGraph(GRAPH_B_IRI, graph_b);
// //Get the Name of all the people in the default Graph
// // const query= `
// // PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
// // PREFIX foaf: <http://xmlns.com/foaf/0.1>
// // SELECT ?name
// // WHERE{
// // ?s a foaf:Person .
// // ?s rdfs:label ?label .
// // }`
// const query = `
// PREFIX foaf: <http://xmlns.com/foaf/0.1/>
// SELECT ?name
// WHERE {
// ?s foaf:name ?name .
// }`
// // Creates a plan builder for the RDF dataset
// const builder = new PlanBuilder(dataset);
// // Get an iterator to evaluate the query
// const iterator = builder.build(query);
// //read results
// iterator.subscribe(
// binding => console.log(bindings),
// err => console.error(err),
// () => console.log('Query evaluation complete')
// );
///////////////////////////////////////////////////////////Integration///////////////////////////////////////////////////////////
DistributedBrokers = ["mqtt.eclipse.org", "test.mosquitto.org","broker.hivemq.com"]; DistributedBrokers = ["mqtt.eclipse.org", "test.mosquitto.org","broker.hivemq.com"];
DistributedBrokersPorts = [1883,1883,1883]; DistributedBrokersPorts = [1883,1883,1883];
function makeTopic(length) { function makeTopic(length) {

View file

@ -1,63 +1,37 @@
const Wallet = require('../wallet'); const Wallet = require('../wallet');
const CoinTransaction = require('../wallet/CoinTransaction'); const Transaction = require('../wallet/transaction');
const MetaDataTransaction = require('../wallet/MetaDataTransaction');
//const MetaDataPool= require('../wallet/metaData-Pool');
const { MaxNumOfCoinTransactions, MaxNumOfMetadataTransactions} = require('../config');
var TransactionPointer;
var NumberOfClearedCoins;
var NumberOfClearedMeta;
class Miner { class Miner {
constructor(blockchain, transactionPool, wallet, p2pServer) { constructor(blockchain, transactionPool, wallet, p2pServer) {
this.blockchain = blockchain; this.blockchain = blockchain;
this.transactionPool = transactionPool; this.transactionPool = transactionPool;
this.wallet = wallet; this.wallet = wallet;
this.p2pServer = p2pServer; this.p2pServer = p2pServer;
} }
mine() { mine() {
const validTransactions = this.transactionPool.validTransactions();
//const validCoinTransactions = this.transactionPool.validCoinTransactions(); Temeperarly changed without checking transaction validity validTransactions.push(
var SelectedCoinTransactions = this.transactionPool.cointransactions.slice(0, MaxNumOfCoinTransactions); Transaction.rewardTransaction(this.wallet, Wallet.blockchainWallet())
var SelectedMetadataTransactions = this.transactionPool.metaDataTransactions.slice(0, MaxNumOfMetadataTransactions); );
//const validTransactions = validCoinTransactions.Concat(validMetaDataTransactions); console.log(validTransactions);
// SelectedCoinTransactions = validCoinTransactions.splice (0, MaxNumOfCoinTransactions); //this will return only limited number of transactions to be stored console.log("//////");
// for (TransactionPointer=0; TransactionPointer<MaxNumOfCoinTransactions; TransactionPointer++){ const validMetadataS = this.transactionPool.validMetadataS();
// SelectedCoinTransactions.push(validCoinTransactions[TransactionPointer]); // for (let i =0; i <validMetadataS.length; i++){
// } // validTransactions.push(validMetadataS[i]);
// SelectedMetadataTransactions = validMetadataTransactions.splice (0, MaxNumOfMetadataTransactions);
// for (TransactionPointer=0; TransactionPointer<MaxNumOfCoinTransactions; TransactionPointer++){
// SelectedCoinTransactions.push(validCoinTransactions[TransactionPointer]);
// }
// include a reward transaction for the miner
SelectedCoinTransactions.push(CoinTransaction.rewardCoinTransaction(this.wallet, Wallet.blockchainWallet()));
//CoinTransaction.rewardCoinTransaction(this.wallet, Wallet.blockchainWallet()));
// create a block consisting of the valid transactions
const block = this.blockchain.addBlock([SelectedCoinTransactions,SelectedMetadataTransactions]);
//const block = this.blockchain.addBlock(validTransactions);
// synchronize chains in the peer-to-peer server
this.p2pServer.syncChains();
// clear the transaction pool
// broadcast to every miner to clear their transaction pools
// if (validCoinTransactions.length>MaxNumOfCoinTransactions){
// this.transactionPool.clearCoin();// clears only selected cointransactions
this.transactionPool.clearCoin(SelectedCoinTransactions.length-1);
this.transactionPool.clearMeta(SelectedMetadataTransactions.length);
this.p2pServer.broadcastClearCoinTransactions();
this.p2pServer.broadcastClearMetadataTransactions();
SelectedCoinTransactions = [];
SelectedMetadataTransactions =[];
// }
// else {
// this.transactionPool.clearAll();
// this.p2pServer.broadcastClearAllTransactions();
// } // }
console.log(validTransactions);
// const validMetadataS = this.transactionPool.metadataS;
const block = this.blockchain.addBlock([validTransactions, validMetadataS]);
this.p2pServer.syncChains();
this.transactionPool.clear();
this.p2pServer.broadcastClearTransactions();
return block; return block;
} }
} }
//module.exports = {NumberOfClearedCoins, NumberOfClearedMeta};
module.exports = Miner; module.exports = Miner;

View file

@ -1,124 +1,104 @@
const Websocket = require('ws'); const Websocket = require('ws');
const P2P_PORT = process.env.P2P_PORT || 5001;
const P2P_PORT = process.env.P2P_PORT || 5000;
const peers = process.env.PEERS ? process.env.PEERS.split(',') : []; const peers = process.env.PEERS ? process.env.PEERS.split(',') : [];
const MESSAGE_TYPES = { const MESSAGE_TYPES = {
chain: 'CHAIN', chain: 'CHAIN',
cointransaction: 'COINTRANSACTION', transaction: 'TRANSACTION',
clear_payment_transactions: 'CLEAR_Payment_TRANSACTIONS', clear_transactions: 'CLEAR_TRANSACTIONS',
clear_meta_transactions: 'CLEAR_META_TRANSACTIONS', metadata: 'METADATA'
clear_Comp_transactions: 'CLEAR_COMP_TRANSACTIONS', };
clear_Integration_transactions: 'CLEAR_Integration_TRANSACTIONS',
metaDataTransaction: 'METADATATRANSACTION',};
class P2pServer { class P2pServer {
constructor(blockchain, transactionPool) { constructor(blockchain, transactionPool) {
this.blockchain = blockchain; this.blockchain = blockchain;
this.transactionPool = transactionPool; this.transactionPool = transactionPool;
this.sockets = [];} this.sockets = [];
}
listen() { listen() {
const server = new Websocket.Server({ port: P2P_PORT }); const server = new Websocket.Server({ port: P2P_PORT });
server.on('connection', socket => this.connectSocket(socket)); server.on('connection', socket => this.connectSocket(socket));
this.connectToPeers(); this.connectToPeers();
console.log(`Listening for peer-to-peer connections on: ${P2P_PORT}`);}
connectToPeers() { console.log(`Listening for peer-to-peer connections on: ${P2P_PORT}`);
}
connectToPeers() {
peers.forEach(peer => { peers.forEach(peer => {
const socket = new Websocket(peer); const socket = new Websocket(peer);
socket.on('open', () => this.connectSocket(socket)); });}
socket.on('open', () => this.connectSocket(socket));
});
}
connectSocket(socket) { connectSocket(socket) {
this.sockets.push(socket); this.sockets.push(socket);
console.log('Socket connected'); console.log('Socket connected');
this.messageHandler(socket); this.messageHandler(socket);
this.sendChain(socket);}
messageHandler(socket) { this.sendChain(socket);
}
messageHandler(socket) {
socket.on('message', message => { socket.on('message', message => {
const data = JSON.parse(message); const data = JSON.parse(message);
switch(data.type) { switch(data.type) {
case MESSAGE_TYPES.chain: case MESSAGE_TYPES.chain:
this.blockchain.replaceChain(data.chain); this.blockchain.replaceChain(data.chain);
break; break;
case MESSAGE_TYPES.paymenttransaction: case MESSAGE_TYPES.transaction:
this.transactionPool.updateOrAddPaymentTransaction( this.transactionPool.updateOrAddTransaction(data.transaction);
data.Paymenttransaction);
break; break;
case MESSAGE_TYPES.metaDataTransaction: case MESSAGE_TYPES.metadata:
this.transactionPool.updateOrAddMetaDataTransaction( this.transactionPool.updateOrAddMetadata(data.metadata);
data.metaDataTransaction);
break;
case MESSAGE_TYPES.CompTransaction:
this.transactionPool.updateOrAddCompTransaction(
data.CompTransaction);
break;
case MESSAGE_TYPES.IntegrationTransaction:
this.transactionPool.updateOrAddIntegrationTransaction(
data.IntegrationTransaction);
break;
case MESSAGE_TYPES.clear_Payment_transactions:
this.transactionPool.clearPayment(this.blockchain.chain[this.
blockchain.chain.length-1].data[0].length-1);
break; break;
case MESSAGE_TYPES.clear_meta_transactions: case MESSAGE_TYPES.clear_transactions:
this.transactionPool.clearMeta(this.blockchain.chain[this. this.transactionPool.clear();
blockchain.chain.length-1].data[1].length);
break; break;
case MESSAGE_TYPES.clear_comp_transactions: }
this.transactionPool.clearMeta(this.blockchain.chain[this. });
blockchain.chain.length-1].data[1].length); }
break;
case MESSAGE_TYPES.clear_intgration_transactions:
this.transactionPool.clearMeta(this.blockchain.chain[this.
blockchain.chain.length-1].data[1].length);
break;}});}
sendChain(socket) { sendChain(socket) {
socket.send(JSON.stringify({ socket.send(JSON.stringify({
type: MESSAGE_TYPES.chain, type: MESSAGE_TYPES.chain,
chain: this.blockchain.chain}));} chain: this.blockchain.chain
ClearedPayments (socket){ }));
}
sendTransaction(socket, transaction) {
socket.send(JSON.stringify({ socket.send(JSON.stringify({
type: MESSAGE_TYPES.clear_payment_transactions,})); } type: MESSAGE_TYPES.transaction,
ClearedMeta (socket){ transaction
socket.send(JSON.stringify({ }));
type: MESSAGE_TYPES.clear_meta_transactions,}));} }
ClearedComp (socket){
socket.send(JSON.stringify({ sendMetadata(socket, metadata) {
type: MESSAGE_TYPES.clear_comp_transactions,}));}
ClearedIntegration (socket){
socket.send(JSON.stringify({
type: MESSAGE_TYPES.clear_integration_transactions,}));}
sendPaymentTransaction(socket, paymenttransaction) {
socket.send(JSON.stringify({
type: MESSAGE_TYPES.paymenttransaction,
paymenttransaction}));}
sendMetaDataTransaction(socket, metaDataTransaction) {
socket.send(JSON.stringify({ socket.send(JSON.stringify({
type: MESSAGE_TYPES.metaDataTransaction, type: MESSAGE_TYPES.metadata,
metaDataTransaction}));} metadata
sendIntegrationTransaction(socket, integrationTransaction) { }));
socket.send(JSON.stringify({ }
type: MESSAGE_TYPES.integrationTransaction,
integrationTransaction}));}
sendCompTransaction(socket, compTransaction) {
socket.send(JSON.stringify({
type: MESSAGE_TYPES.compTransaction,
compTransaction}));}
syncChains() { syncChains() {
this.sockets.forEach(socket => this.sendChain(socket));} this.sockets.forEach(socket => this.sendChain(socket));
broadcastPaymentTransaction(paymenttransaction) { }
this.sockets.forEach(socket => this.sendPaymentTransaction(socket,
paymenttransaction));} broadcastTransaction(transaction) {
broadcastMetaDataTransaction(metaDataTransaction) { this.sockets.forEach(socket => this.sendTransaction(socket, transaction));
this.sockets.forEach(socket => this.sendMetaDataTransaction(socket, }
metaDataTransaction));}
broadcastCompTransaction(compTransaction) { broadcastMetadata(metadata) {
this.sockets.forEach(socket => this.sendCompTransaction(socket, this.sockets.forEach(socket => this.sendMetadata(socket, metadata));
CompTransaction));} }
broadcastIntegrationTransaction(integrationTransaction) {
this.sockets.forEach(socket => this.sendIntegrationTransaction(socket, broadcastClearTransactions() {
integrationTransaction));} this.sockets.forEach(socket => socket.send(JSON.stringify({
broadcastClearPaymentTransactions() { type: MESSAGE_TYPES.clear_transactions
this.sockets.forEach(socket => this.ClearedCoins(socket));} })));
broadcastClearMetadataTransactions() { }
this.sockets.forEach(socket => this.ClearedMeta(socket));} }
broadcastClearCompTransactions() {
this.sockets.forEach(socket => this.ClearedComp(socket));} module.exports = P2pServer;
broadcastClearIntegrationTransactions() {
this.sockets.forEach(socket => this.ClearedIntegration(socket));}}
module.exports = P2pServer ;

View file

@ -1,6 +0,0 @@
const swaggerAutogen = require('swagger-autogen')()
const outputFile = './swagger_output.json'
const APIfiles = ['./index.js']
swaggerAutogen(outputFile, APIfiles)

View file

@ -1,369 +0,0 @@
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "REST API",
"description": ""
},
"host": "localhost:3000",
"basePath": "/",
"schemes": [
"http"
],
"paths": {
"/blocks": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/MetaDataTransactions": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/CoinTransactions": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/Transactions": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/mine-transactions": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/public-key": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/Balance": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/mine": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"data": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/IoTdeviceRegistration": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"Name": {
"example": "any"
},
"Geo": {
"example": "any"
},
"IP_URL": {
"example": "any"
},
"Topic_Token": {
"example": "any"
},
"Permission": {
"example": "any"
},
"RequestDetail": {
"example": "any"
},
"OrgOwner": {
"example": "any"
},
"DepOwner": {
"example": "any"
},
"PrsnOwner": {
"example": "any"
},
"PaymentPerKbyte": {
"example": "any"
},
"PaymentPerMinute": {
"example": "any"
},
"Protocol": {
"example": "any"
},
"MessageAttributes": {
"example": "any"
},
"Interval": {
"example": "any"
},
"FurtherDetails": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/IoTdevicePaymentTransaction": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"Recipient_payment_address": {
"example": "any"
},
"Amount_of_money": {
"example": "any"
},
"Payment_method": {
"example": "any"
},
"Further_details": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/UploadMetafile": {
"post": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
},
"201": {
"description": "Created"
}
}
}
},
"/selectedMeta": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"Name": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/sparql": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"Select": {
"example": "any"
},
"subject": {
"example": "any"
},
"predicate": {
"example": "any"
},
"object": {
"example": "any"
},
"Limit": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/sparql2": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"Select": {
"example": "any"
},
"subject": {
"example": "any"
},
"predicate": {
"example": "any"
},
"object": {
"example": "any"
},
"Limit": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/IoTdeviceIntegration-Control": {
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"IoTDeviceID": {
"example": "any"
},
"paymentTransactionID": {
"example": "any"
},
"Duration": {
"example": "any"
},
"Protocol": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/IoTdataObtainingAndForward": {
"get": {
"description": "",
"parameters": [],
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}

View file

@ -2,52 +2,54 @@ const ChainUtil = require('../chain-util');
const { DIFFICULTY, MINE_RATE } = require('../config'); const { DIFFICULTY, MINE_RATE } = require('../config');
class Block { class Block {
constructor(timestamp,BlockNum, lastHash, hash, data, nonce, constructor(timestamp, lastHash, hash, data, nonce, difficulty) {
difficulty) {
this.timestamp = timestamp; this.timestamp = timestamp;
this.BlockNum = BlockNum;
this.lastHash = lastHash; this.lastHash = lastHash;
this.hash = hash; this.hash = hash;
this.data = data; this.data = data;
this.nonce = nonce; this.nonce = nonce;
this.difficulty = difficulty || DIFFICULTY; this.difficulty = difficulty || DIFFICULTY;
} }
toString() { toString() {
return `Block - return `Block -
Timestamp : ${this.timestamp} Timestamp : ${this.timestamp}
BlockNum : ${this.BlockNum}
Last Hash : ${this.lastHash.substring(0, 10)} Last Hash : ${this.lastHash.substring(0, 10)}
Hash : ${this.hash.substring(0, 10)} Hash : ${this.hash.substring(0, 10)}
Nonce : ${this.nonce} Nonce : ${this.nonce}
Difficulty: ${this.difficulty} Difficulty: ${this.difficulty}
Data : ${this.data[0].length}`; Data : ${this.data}`;
} }
static genesis() { static genesis() {
return new this('Genesis-time',0, '-----', 'First-Hash', return new this('Genesis time', '-----', 'f1r57-h45h', [], 0, DIFFICULTY);
[], 0, DIFFICULTY);
} }
static mineBlock(lastBlock, data) { static mineBlock(lastBlock, data) {
let hash, timestamp; let hash, timestamp;
const lastHash = lastBlock.hash; const lastHash = lastBlock.hash;
let { difficulty } = lastBlock; let { difficulty } = lastBlock;
let nonce = 0; let nonce = 0;
let BlockNum = lastBlock.BlockNum + 1;
do { do {
nonce++; nonce++;
timestamp = Date.now(); timestamp = Date.now();
difficulty = Block.adjustDifficulty(lastBlock, timestamp); difficulty = Block.adjustDifficulty(lastBlock, timestamp);
hash = Block.hash(timestamp, lastHash, data, nonce, difficulty); hash = Block.hash(timestamp, lastHash, data, nonce, difficulty);
} while (hash.substring(0, difficulty) !== '0'.repeat(difficulty)); } while (hash.substring(0, difficulty) !== '0'.repeat(difficulty));
return new this(timestamp,BlockNum, lastHash, hash, data, nonce,
difficulty);} return new this(timestamp, lastHash, hash, data, nonce, difficulty);
static hash(timestamp,lastHash, data, nonce, difficulty) {
return ChainUtil.hash(`${timestamp}${lastHash}${data}${nonce}
${difficulty}`).toString();
} }
static hash(timestamp, lastHash, data, nonce, difficulty) {
return ChainUtil.hash(`${timestamp}${lastHash}${data}${nonce}${difficulty}`).toString();
}
static blockHash(block) { static blockHash(block) {
const { timestamp, lastHash, data, nonce, difficulty } = block; const { timestamp, lastHash, data, nonce, difficulty } = block;
return Block.hash(timestamp, lastHash, data, nonce, difficulty); return Block.hash(timestamp, lastHash, data, nonce, difficulty);
} }
static adjustDifficulty(lastBlock, currentTime) { static adjustDifficulty(lastBlock, currentTime) {
let { difficulty } = lastBlock; let { difficulty } = lastBlock;
difficulty = lastBlock.timestamp + MINE_RATE > currentTime ? difficulty = lastBlock.timestamp + MINE_RATE > currentTime ?
@ -55,4 +57,5 @@ class Block {
return difficulty; return difficulty;
} }
} }
module.exports = Block; module.exports = Block;

View file

@ -1,296 +0,0 @@
Block -
Timestamp : 1581892713022
Last Hash : f1r57-h45h
Hash : 0000f64170
Nonce : 94889
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581892714610
Last Hash : 0000f64170
Hash : 000001941a
Nonce : 121452
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581892736795
Last Hash : 000004bdbe
Hash : 0000af3e65
Nonce : 1109949
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581892725766
Last Hash : 00001402a6
Hash : 000004bdbe
Nonce : 114910
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581892752249
Last Hash : 0000145513
Hash : 0000085224
Nonce : 484976
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581892762535
Last Hash : 0000085224
Hash : 00001cd286
Nonce : 995419
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581892763338
Last Hash : 00001cd286
Hash : 00000c8fa5
Nonce : 80136
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581892724628
Last Hash : 000001941a
Hash : 00001402a6
Nonce : 964391
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581892746837
Last Hash : 0000af3e65
Hash : 0005cb06ba
Nonce : 960133
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581892747191
Last Hash : 0005cb06ba
Hash : 0000145513
Nonce : 35175
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581894328935
Last Hash : f1r57-h45h
Hash : 0000027b9b
Nonce : 41326
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581894353562
Last Hash : 00084950c6
Hash : 0000cc1d6a
Nonce : 16931
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581894360160
Last Hash : 0000cc1d6a
Hash : 00000a55b4
Nonce : 681141
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581894370451
Last Hash : 00000a55b4
Hash : 000062a73f
Nonce : 1065366
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581894372244
Last Hash : 000062a73f
Hash : 000006be7e
Nonce : 182919
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581894383168
Last Hash : 000006be7e
Hash : 0000947649
Nonce : 1129947
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581894385832
Last Hash : 0000947649
Hash : 0000063c81
Nonce : 274322
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581894339035
Last Hash : 0000027b9b
Hash : 0007a1423c
Nonce : 995688
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581894343276
Last Hash : 0007a1423c
Hash : 00008d4e58
Nonce : 379871
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581894353389
Last Hash : 00008d4e58
Hash : 00084950c6
Nonce : 1043732
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581914042391
Last Hash : f1r57-h45h
Hash : 00005dbdc7
Nonce : 16289
Difficulty: 4
Data : [object Object],[object Object],[object Object]
Block -
Timestamp : 1581914052481
Last Hash : 00005dbdc7
Hash : 0002715612
Nonce : 945209
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581914052947
Last Hash : 0002715612
Hash : 00006f867b
Nonce : 44547
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581914073313
Last Hash : 0002826b45
Hash : 0000595eff
Nonce : 7524
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581914083348
Last Hash : 0000595eff
Hash : 000387395e
Nonce : 974338
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581914083523
Last Hash : 000387395e
Hash : 0000d7ada9
Nonce : 15912
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581914091333
Last Hash : 0000d7ada9
Hash : 00000ce8de
Nonce : 733896
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581914063218
Last Hash : 000873faba
Hash : 0000c9a5a8
Nonce : 23871
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581914073229
Last Hash : 0000c9a5a8
Hash : 0002826b45
Nonce : 1004347
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581914062966
Last Hash : 00006f867b
Hash : 000873faba
Nonce : 964936
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581914568417
Last Hash : f1r57-h45h
Hash : 0000646876
Nonce : 8365
Difficulty: 4
Data : [object Object],[object Object],[object Object]
Block -
Timestamp : 1581914578440
Last Hash : 0000646876
Hash : 00034edf74
Nonce : 948376
Difficulty: 3
Data : [object Object],
Block -
Timestamp : 1581914579386
Last Hash : 00034edf74
Hash : 00003f7371
Nonce : 88529
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581914847561
Last Hash : f1r57-h45h
Hash : 0000a45f66
Nonce : 58810
Difficulty: 4
Data : [object Object],[object Object]
Block -
Timestamp : 1581914850074
Last Hash : 0000a45f66
Hash : 0000053121
Nonce : 229566
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581914860093
Last Hash : 0000053121
Hash : 0000f0fa54
Nonce : 968591
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1581915028382
Last Hash : f1r57-h45h
Hash : 000012342d
Nonce : 74682
Difficulty: 4
Data : [object Object],[object Object]
Block -
Timestamp : 1581915029059
Last Hash : 000012342d
Hash : 000009fa64
Nonce : 59238
Difficulty: 5
Data : [object Object],
Block -
Timestamp : 1581915039087
Last Hash : 000009fa64
Hash : 0000219469
Nonce : 963908
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1631336762365
Last Hash : f1r57-h45h
Hash : 0000cb4fc4
Nonce : 87088
Difficulty: 4
Data : [object Object],
Mined Block
Block -
Timestamp : 1631336852594
Last Hash : f1r57-h45h
Hash : 0000fa68c7
Nonce : 31088
Difficulty: 4
Data : [object Object],
Block -
Timestamp : 1631337166316
Last Hash : f1r57-h45h
Hash : 0000b73e4b
Nonce : 31185
Difficulty: 4
Data : [object Object],
Mined Block

View file

@ -1,6 +1,6 @@
const EC = require('elliptic').ec; const EC = require('elliptic').ec;
const SHA256 = require('crypto-js/sha256'); const SHA256 = require('crypto-js/sha256');
const uuidV1 = require('uuid/v1'); const { v1 : uuidV1 } = require ('uuid');
const ec = new EC('secp256k1'); const ec = new EC('secp256k1');
class ChainUtil { class ChainUtil {

View file

@ -1,8 +1,6 @@
const DIFFICULTY = 5; const DIFFICULTY = 3;
const MINE_RATE = 20000; const MINE_RATE = 3000;
const INITIAL_BALANCE = 500; const INITIAL_BALANCE = 500;
const MINING_REWARD = 50; const MINING_REWARD = 50;
const MaxNumOfCoinTransactions = 3;
const MaxNumOfMetadataTransactions = 3;
module.exports = { DIFFICULTY, MINE_RATE, INITIAL_BALANCE, MINING_REWARD, MaxNumOfCoinTransactions, MaxNumOfMetadataTransactions} ; module.exports = { DIFFICULTY, MINE_RATE, INITIAL_BALANCE, MINING_REWARD };

View file

@ -1,5 +0,0 @@
{
"env": {
"MONGO_ATLAS_PW":"11112222-m"
}
}

25145
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,55 +1,37 @@
{ {
"name": "Sen-Sha-Mart", "name": "senshamartproject",
"version": "6.0.0", "version": "1.0.0",
"description": "A novel Marketplace for sharing sensors in decentralized environment", "description": "A novel Marketplace for sharing sensors in decentralized environment",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "jest --watchAll", "test": "jest --watchAll",
"dev-test": "nodemon dev-test", "dev-test": "nodemon dev-test",
"start": "node ./app", "start": "node ./app",
"dev": "nodemon ./app", "dev": "nodemon ./app"
"sparql": "nodemon ./test/comunicaSPARQL",
"jsonld": "nodemon ./test/jsonld",
"sparqlEngine": "nodemon ./test/sparqlEngine",
"N3": "nodemon ./test/N3sudo yarn ",
"swagger-autogen": "node ./app/swagger.js"
}, },
"jest": { "jest": {
"testEnvironment": "node" "testEnvironment": "node"
}, },
"keywords": [], "keywords": [],
"author": "AnasDawod", "author": "Anas Dawod",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"jest": "^22.1.4", "jest": "^29.2.0",
"nodemon": "^1.14.12", "jest-cli": "^29.2.0",
"swagger-autogen": "^2.22.0" "nodemon": "^2.0.20"
}, },
"dependencies": { "dependencies": {
"@comunica/actor-init-sparql": "^1.9.1", "@comunica/query-sparql": "^2.5.2",
"@comunica/actor-init-sparql-file": "^1.9.1",
"@comunica/actor-init-sparql-rdfjs": "^1.9.1",
"aedes": "^0.42.5", "aedes": "^0.42.5",
"body-parser": "^1.18.2", "body-parser": "^1.20.1",
"crypto-js": "^3.1.9-1", "crypto-js": "^4.1.1",
"elliptic": "^6.4.0", "elliptic": "^6.5.4",
"express": "^4.16.2", "express": "^4.18.2",
"http": "0.0.0",
"jsonld": "^1.7.0", "jsonld": "^1.7.0",
"level": "^5.0.1",
"level-browserify": "^2.0.0",
"levelgraph": "^2.1.1",
"lodash": "^4.17.11",
"log4js": "^6.1.2",
"morgan": "^1.9.1",
"mosca": "^2.8.3",
"mqtt": "^4.1.0", "mqtt": "^4.1.0",
"multer": "^1.3.1", "multer": "^1.3.1",
"n3": "^1.2.0", "n3": "^1.2.0",
"sparql-engine": "^0.5.3", "uuid": "^9.0.0",
"stream": "^0.0.2", "ws": "^8.9.0"
"swagger-ui-express": "^4.5.0",
"uuid": "^3.2.1",
"ws": "^4.0.0"
} }
} }

BIN
test/.DS_Store vendored

Binary file not shown.

View file

@ -1,49 +0,0 @@
const N3 = require('n3');
const newEngine = require('@comunica/actor-init-sparql-rdfjs').newEngine;
const jsonld = require('jsonld');
const N3Store = require('n3').Store;
const DataFactory = require('n3').DataFactory;
const myEngine = newEngine();
const parser = new N3.Parser();
const store = new N3Store();
const doc = {
"http://schema.org/name": "Manu Sporny",
"http://schema.org/url": {"@id": "http://manu.sporny.org/"},
"http://schema.org/image": {"@id": "http://manu.sporny.org/images/manu.png"}
};
jsonld.toRDF(doc, {format: 'application/n-quads'}, (err, nquads) => {
// nquads is a string of N-Quads
//console.log(nquads);
parser.parse(
nquads,
(error, quad, prefixes) => {
if (quad)
//console.log(quad);
store.addQuad(quad);
else
console.log(store);
const start = async function (a,b){
const result = await myEngine.query('SELECT * { ?s ?p <http://manu.sporny.org/>. ?s ?p ?o} LIMIT 100',
{ sources: [ { value: store } ] });
//result.bindingsStream.on('data', (data) => {
// Each data object contains a mapping from variables to RDFJS terms.
console.log(result);
// console.log(data.get('?p'));
// console.log(data.get('?o'));
// });
};
start();
});
});

View file

@ -1,68 +0,0 @@
const newEngine = require('@comunica/actor-init-sparql').newEngine;
const N3 = require('n3');
const jsonld = require('jsonld')
const DataFactory = require('n3').DataFactory;
const parser = new N3.Parser({format: 'application/n-quads'});
const store = new N3.Store();
const myEngine = newEngine();
const doc = {
"http://schema.org/name": "Manu Sporny",
"http://schema.org/url": {"@id": "http://manu.sporny.org/"},
"http://schema.org/image": {"@id": "http://manu.sporny.org/images/manu.png"}
};
jsonld.toRDF(doc, {format: 'application/n-quads'}, (err, nquads) => {
// nquads is a string of N-Quads
// console.log(nquads);
var quad= [];
parser.parse(
nquads,
(error, quadN, prefixes) => {
// console.log(quadN)
if (quadN)
{
store.addQuad(DataFactory.quad(
DataFactory.namedNode(quadN.subject.id), DataFactory.namedNode(quadN.predicate.id), DataFactory.namedNode(quadN.object.id)));
}
else
console.log("finished");
// console.log(quadN)
});
const start = async function (a,b){
const result = await myEngine.query('SELECT * WHERE {?s ?p ?o } LIMIT 100',
{ sources: [{ type: 'rdfjsSource', value: store}] })
result.bindingsStream.on('data', (data) => console.log(data.toObject()));
};
start()
console.log(quad)
// store.addQuad(DataFactory.quad(
// DataFactory.namedNode(quad.subject.id), DataFactory.namedNode(quad.predicate.id), DataFactory.namedNode(quad.object.id)));
// store.addQuad(DataFactory.quad(
// DataFactory.namedNode('http://schema.org/image'), DataFactory.namedNode('http://manu.sporny.org/images/manu.png'), DataFactory.namedNode('http://schema.org/name')));
// store.addQuad(DataFactory.quad(
// DataFactory.namedNode('http://schema.org/url'), DataFactory.namedNode('http://manu.sporny.org/'), DataFactory.namedNode('http://dbpedia.org/resource/Ghent')));
//console.log(store)
// const start = async function (a,b){
// const result = await myEngine.query('SELECT * WHERE {?s ?p <http://manu.sporny.org/images/manu.png>. ?s ?p ?o } LIMIT 100',
// { sources: [{ type: 'rdfjsSource', value: store}] })
// result.bindingsStream.on('data', (data) => console.log(data.toObject()));
// };
// start()
});
// store.addQuad(DataFactory.quad(
// DataFactory.namedNode('http://schema.org/image'), DataFactory.namedNode('http://manu.sporny.org/images/manu.png'), DataFactory.namedNode('http://schema.org/name')));
// store.addQuad(DataFactory.quad(
// DataFactory.namedNode('http://schema.org/url'), DataFactory.namedNode('http://manu.sporny.org/'), DataFactory.namedNode('http://dbpedia.org/resource/Ghent')));
// // console.log(store)

View file

@ -1,20 +0,0 @@
const jsonld = require('jsonld');
const doc = {
"http://schema.org/name": "Manu Sporny",
"http://schema.org/url": {"@id": "http://manu.sporny.org/"},
"http://schema.org/PrsnOwner": "0400985d4fca84fe0e8cff7e8902326a6703ba182cc8d6d8e20866b0acfc79ecb6bfd3d3b5d6ad7f48cd10fadc6d4348cab918f13db2ebb387ba16c57802bf47b1",
};
jsonld.toRDF(doc, {format: 'application/n-quads'}, (err, nquads) => {
// nquads is a string of N-Quads
console.log(nquads);
});
// const start = async function (a,b){
// const rdf = await jsonld.toRDF(doc, {format: 'application/n-quads'});
// console.log(rdf);
// };
// start();

View file

@ -1,78 +0,0 @@
'use strict'
const { BindingBase, HashMapDataset, Graph, PlanBuilder } = require('sparql-engine')
const level = require('level')
const levelgraph = require('levelgraph')
const { Transform } = require('stream')
// An utility class used to convert LevelGraph bindings
// into a format undestood by sparql-engine
class FormatterStream extends Transform {
constructor () {
super({objectMode: true})
}
_transform (item, encoding, callback) {
// Transform LevelGraph objects into set of mappings
// using BindingBase.fromObject
this.push(BindingBase.fromObject(item))
callback()
}
}
class LevelRDFGraph extends Graph {
constructor (db) {
super()
this._db = db
}
evalBGP (bgp) {
// rewrite variables using levelgraph API
bgp = bgp.map(t => {
if (t.subject.startsWith('?')) {
t.subject = this._db.v(t.subject.substring(1))
}
if (t.predicate.startsWith('?')) {
t.predicate = this._db.v(t.predicate.substring(1))
}
if (t.object.startsWith('?')) {
t.object = this._db.v(t.object.substring(1))
}
return t
})
// Transform the Stream returned by LevelGraph into an Stream of Bindings
return new FormatterStream(this._db.searchStream(bgp))
}
}
const db = levelgraph(level('testing_db'))
// insert some triples
var triple1 = { subject: 'http://example.org#a1', predicate: 'http://xmlns.com/foaf/0.1/name', object: '"c"' }
var triple2 = { subject: 'http://example.org#a2', predicate: 'http://xmlns.com/foaf/0.1/name', object: '"d"' }
db.put([triple1, triple2], () => {
const graph = new LevelRDFGraph(db)
const dataset = new HashMapDataset('http://example.org#default', graph)
const query = `
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE {
?s foaf:name ?name .
}`
// Creates a plan builder for the RDF dataset
const builder = new PlanBuilder(dataset)
// Get an iterator to evaluate the query
const iterator = builder.build(query)
// Read results
iterator.subscribe(bindings => {
console.log('Find solutions:', bindings.toObject())
}, err => {
console.error('error', err)
}, () => {
console.log('Query evaluation complete!')
})
})

View file

@ -0,0 +1,793 @@
[ {
"@id" : "_:genid1",
"@type" : [ "http://xmlns.com/foaf/0.1/Agent" ],
"http://xmlns.com/foaf/0.1/name" : [ {
"@language" : "en",
"@value" : "W3C/OGC Spatial Data on the Web Working Group"
} ]
}, {
"@id" : "_:genid2",
"@type" : [ "http://www.w3.org/ns/sosa/QuantityValue" ]
}, {
"@id" : "_:genid3",
"@type" : [ "http://www.w3.org/2006/time#TemporalEntity" ]
}, {
"@id" : "_:genid4",
"@type" : [ "http://xmlns.com/foaf/0.1/Agent" ],
"http://xmlns.com/foaf/0.1/name" : [ {
"@language" : "en",
"@value" : "W3C/OGC Spatial Data on the Web Working Group"
} ]
}, {
"@id" : "_:genid5",
"@type" : [ "http://xmlns.com/foaf/0.1/Agent" ],
"http://xmlns.com/foaf/0.1/name" : [ {
"@language" : "en",
"@value" : "W3C/OGC Spatial Data on the Web Working Group"
} ]
}, {
"@id" : "http://example.org/data/Observation/346344",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/Observation" ],
"http://www.w3.org/ns/sosa/hasFeatureOfInterest" : [ {
"@id" : "http://www.w3.org/ns/sosa/'Office_temperature'"
} ],
"http://www.w3.org/ns/sosa/madeBySensor" : [ {
"@id" : "http://www.w3.org/ns/sosa/'DHT11'"
} ],
"http://www.w3.org/ns/sosa/observedProperty" : [ {
"@id" : "http://www.w3.org/ns/sosa/'air_temperature'"
} ]
}, {
"@id" : "http://example.org/data/Observation/346345",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/Observation" ],
"http://www.w3.org/ns/sosa/hasFeatureOfInterest" : [ {
"@id" : "http://www.w3.org/ns/sosa/'Office_Humidity'"
} ],
"http://www.w3.org/ns/sosa/madeBySensor" : [ {
"@id" : "http://www.w3.org/ns/sosa/'DHT11'"
} ],
"http://www.w3.org/ns/sosa/observedProperty" : [ {
"@id" : "http://www.w3.org/ns/sosa/'air_Humidity'"
} ]
}, {
"@id" : "http://purl.org/dc/terms/created",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/dc/terms/creator",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/dc/terms/description",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/dc/terms/license",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/dc/terms/rights",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/dc/terms/title",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/vocab/vann/preferredNamespacePrefix",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://purl.org/vocab/vann/preferredNamespaceUri",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://schema.org/domainIncludes",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://schema.org/rangeIncludes",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://www.w3.org/2004/02/skos/core#definition",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://www.w3.org/2004/02/skos/core#example",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://www.w3.org/2004/02/skos/core#note",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://www.w3.org/2006/time#TemporalEntity",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ]
}, {
"@id" : "http://www.w3.org/ns/sosa/",
"@type" : [ "http://www.w3.org/2002/07/owl#Ontology" ],
"http://purl.org/dc/terms/created" : [ {
"@type" : "http://www.w3.org/2001/XMLSchema#date",
"@value" : "2017-04-17"
} ],
"http://purl.org/dc/terms/creator" : [ {
"@id" : "_:genid1"
} ],
"http://purl.org/dc/terms/description" : [ {
"@language" : "en",
"@value" : "This ontology is based on the SSN Ontology by the W3C Semantic Sensor Networks Incubator Group (SSN-XG), together with considerations from the W3C/OGC Spatial Data on the Web Working Group."
} ],
"http://purl.org/dc/terms/license" : [ {
"@id" : "http://www.opengeospatial.org/ogc/Software"
}, {
"@id" : "http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document"
} ],
"http://purl.org/dc/terms/rights" : [ {
"@value" : "Copyright 2017 W3C/OGC."
} ],
"http://purl.org/dc/terms/title" : [ {
"@language" : "en",
"@value" : "Sensor, Observation, Sample, and Actuator (SOSA) Ontology"
} ],
"http://purl.org/vocab/vann/preferredNamespacePrefix" : [ {
"@value" : "sosa"
} ],
"http://purl.org/vocab/vann/preferredNamespaceUri" : [ {
"@value" : "http://www.w3.org/ns/sosa/"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/'Arduino_UNO_R3'",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/Platform" ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@value" : "Arduino Uno R3"
} ],
"http://www.w3.org/ns/sosa/Owner" : [ {
"@value" : "04f5add581755fad29e698e053f2b923e5a15cc6bad9987bcb4dc79edb36cd54a732faae838841205461717391d0d198604d9d20a6a68b472339e1ff4874188d0a"
} ],
"http://www.w3.org/ns/sosa/hosts" : [ {
"@id" : "http://www.w3.org/ns/sosa/'DHT11'"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/'DHT11'",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/Sensor" ],
"http://purl.org/dc/terms/creator" : [ {
"@value" : "AOSONG"
} ],
"http://purl.org/dc/terms/description" : [ {
"@value" : "Measures the temperature and humidity of the surrounding air.\nWorks on 3.3 - 5.5 volts"
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@value" : "DHT11"
} ],
"http://www.w3.org/ns/sosa/Owner" : [ {
"@value" : "04f5add581755fad29e698e053f2b923e5a15cc6bad9987bcb4dc79edb36cd54a732faae838841205461717391d0d198604d9d20a6a68b472339e1ff4874188d0a"
} ],
"http://www.w3.org/ns/sosa/observes" : [ {
"@id" : "http://www.w3.org/ns/sosa/'air_Humidity'"
}, {
"@id" : "http://www.w3.org/ns/sosa/'air_temperature'"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/'Office_Humidity'",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/FeatureOfInterest" ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@value" : "Office_Humidity"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/'Office_temperature'",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/FeatureOfInterest" ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@value" : "Office_temperature"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/'air_Humidity'",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/ObservableProperty" ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@value" : "air_Humidity"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/'air_temperature'",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/ObservableProperty" ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@value" : "air_temperature"
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/FeatureOfInterest",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "The thing whose property is being estimated or calculated in the course of an Observation to arrive at a Result or whose property is being manipulated by an Actuator, or which is being sampled or transformed in an act of Sampling."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "Feature Of Interest"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "The thing whose property is being estimated or calculated in the course of an Observation to arrive at a Result or whose property is being manipulated by an Actuator, or which is being sampled or transformed in an act of Sampling."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "When measuring the height of a tree, the height is the observed ObservableProperty, 20m may be the Result of the Observation, and the tree is the FeatureOfInterest. A window is a FeatureOfInterest for an automatic window control Actuator."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/ObservableProperty",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "An observable quality (property, characteristic) of a FeatureOfInterest."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "Observable Property"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "An observable quality (property, characteristic) of a FeatureOfInterest."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "The height of a tree, the depth of a water body, or the temperature of a surface are examples of observable properties, while the value of a classic car is not (directly) observable but asserted."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/Observation",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Act of carrying out an (Observation) Procedure to estimate or calculate a value of a property of a FeatureOfInterest. Links to a Sensor to describe what made the Observation and how; links to an ObservableProperty to describe what the result is an estimate of, and to a FeatureOfInterest to detail what that property was associated with."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "Observation"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Act of carrying out an (Observation) Procedure to estimate or calculate a value of a property of a FeatureOfInterest. Links to a Sensor to describe what made the Observation and how; links to an ObservableProperty to describe what the result is an estimate of, and to a FeatureOfInterest to detail what that property was associated with."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "The activity of estimating the intensity of an Earthquake using the Mercalli intensity scale is an Observation as is measuring the moment magnitude, i.e., the energy released by said earthquake."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/Owner",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
}, {
"@id" : "http://www.w3.org/ns/sosa/Platform",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "A Platform is an entity that hosts other entities, particularly Sensors, Actuators, Samplers, and other Platforms."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "Platform"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "A Platform is an entity that hosts other entities, particularly Sensors, Actuators, Samplers, and other Platforms."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "A post, buoy, vehicle, ship, aircraft, satellite, cell-phone, human or animal may act as platforms for (technical or biological) sensors or actuators."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/QuantityValue",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ]
}, {
"@id" : "http://www.w3.org/ns/sosa/Result",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "The Result of an Observation, Actuation, or act of Sampling. To store an observation's simple result value one can use the hasSimpleResult property."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "Result"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "The Result of an Observation, Actuation, or act of Sampling. To store an observation's simple result value one can use the hasSimpleResult property."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "The value 20 as the height of a certain tree together with the unit, e.g., Meter."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/Sensor",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Device, agent (including humans), or software (simulation) involved in, or implementing, a Procedure. Sensors respond to a stimulus, e.g., a change in the environment, or input data composed from the results of prior Observations, and generate a Result. Sensors can be hosted by Platforms."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "Sensor"
} ],
"http://www.w3.org/2000/01/rdf-schema#subClassOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Device, agent (including humans), or software (simulation) involved in, or implementing, a Procedure. Sensors respond to a stimulus, e.g., a change in the environment, or input data composed from the results of prior Observations, and generate a Result. Sensors can be hosted by Platforms."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "Accelerometers, gyroscopes, barometers, magnetometers, and so forth are Sensors that are typically mounted on a modern smart phone (which acts as Platform). Other examples of sensors include the human eyes."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/actsOnProperty",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between an Actuation and the property of a FeatureOfInterest it is acting upon."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "acts on property"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/isActedOnBy"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between an Actuation and the property of a FeatureOfInterest it is acting upon."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "In the activity (Actuation) of automatically closing a window if the temperature in a room drops below 20 degrees Celsius, the property on which the Actuator acts upon is the state of the window as it changes from being open to being closed. "
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/hasFeatureOfInterest",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/FeatureOfInterest"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "A relation between an Observation and the entity whose quality was observed, or between an Actuation and the entity whose property was modified, or between an act of Sampling and the entity that was sampled."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "has feature of interest"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/isFeatureOfInterestOf"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "A relation between an Observation and the entity whose quality was observed, or between an Actuation and the entity whose property was modified, or between an act of Sampling and the entity that was sampled."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "For example, in an Observation of the weight of a person, the FeatureOfInterest is the person and the property is its weight."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/hasResult",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Result"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation linking an Observation or Actuation or act of Sampling and a Result or Sample."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "has result"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/isResultOf"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation linking an Observation or Actuation or act of Sampling and a Result or Sample."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/hasSample",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/FeatureOfInterest"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between a FeatureOfInterest and the Sample used to represent it."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "has sample"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/isSampleOf"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between a FeatureOfInterest and the Sample used to represent it."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/hasSimpleResult",
"@type" : [ "http://www.w3.org/2002/07/owl#DatatypeProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "The simple value of an Observation or Actuation or act of Sampling."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "has simple result"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "The simple value of an Observation or Actuation or act of Sampling."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "For instance, the values 23 or true."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/hosts",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Platform"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Platform"
}, {
"@id" : "http://www.w3.org/ns/sosa/Sensor"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between a Platform and a Sensor, Actuator, Sampler, or Platform, hosted or mounted on it."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "hosts"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/isHostedBy"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between a Platform and a Sensor, Actuator, Sampler, or Platform, hosted or mounted on it."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/isActedOnBy",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between an ActuatableProperty of a FeatureOfInterest and an Actuation changing its state."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "is acted on by"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between an ActuatableProperty of a FeatureOfInterest and an Actuation changing its state."
} ],
"http://www.w3.org/2004/02/skos/core#example" : [ {
"@language" : "en",
"@value" : "In the activity (Actuation) of automatically closing a window if the temperature in a room drops below 20 degrees Celsius, the property on which the Actuator acts upon is the state of the window as it changes from being open to being closed. "
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/isFeatureOfInterestOf",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/FeatureOfInterest"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "A relation between a FeatureOfInterest and an Observation about it, an Actuation acting on it, or an act of Sampling that sampled it."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "is feature of interest of"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "A relation between a FeatureOfInterest and an Observation about it, an Actuation acting on it, or an act of Sampling that sampled it."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/isHostedBy",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Platform"
}, {
"@id" : "http://www.w3.org/ns/sosa/Sensor"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Platform"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between a Sensor, Actuator, Sampler, or Platform, and the Platform that it is mounted on or hosted by."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "is hosted by"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between a Sensor, Actuator, Sampler, or Platform, and the Platform that it is mounted on or hosted by."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/isObservedBy",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/ObservableProperty"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Sensor"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between an ObservableProperty and the Sensor able to observe it."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "is observed by"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/observes"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between an ObservableProperty and the Sensor able to observe it."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/isResultOf",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Result"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation linking a Result to the Observation or Actuation or act of Sampling that created or caused it."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "is result of"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation linking a Result to the Observation or Actuation or act of Sampling that created or caused it."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/isSampleOf",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/FeatureOfInterest"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation from a Sample to the FeatureOfInterest that it is intended to be representative of."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "is sample of"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation from a Sample to the FeatureOfInterest that it is intended to be representative of."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/madeActuation",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between an Actuator and the Actuation it has made."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "made actuation"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/madeByActuator"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between an Actuator and the Actuation it has made."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/madeByActuator",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation linking an Actuation to the Actuator that made that Actuation."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "made by actuator"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation linking an Actuation to the Actuator that made that Actuation."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/madeBySampler",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation linking an act of Sampling to the Sampler (sampling device or entity) that made it."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "made by sampler"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/madeSampling"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation linking an act of Sampling to the Sampler (sampling device or entity) that made it."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/madeBySensor",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Sensor"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between an Observation and the Sensor which made the Observation."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "made by sensor"
} ],
"http://www.w3.org/2002/07/owl#inverseOf" : [ {
"@id" : "http://www.w3.org/ns/sosa/madeObservation"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between an Observation and the Sensor which made the Observation."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/madeObservation",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Sensor"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between a Sensor and an Observation made by the Sensor."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "made observation"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between a Sensor and an Observation made by the Sensor."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/madeSampling",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between a Sampler (sampling device or entity) and the Sampling act it performed."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "made sampling"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between a Sampler (sampling device or entity) and the Sampling act it performed."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/observedProperty",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/ObservableProperty"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation linking an Observation to the property that was observed. The ObservableProperty should be a property of the FeatureOfInterest (linked by hasFeatureOfInterest) of this Observation."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "observed property"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation linking an Observation to the property that was observed. The ObservableProperty should be a property of the FeatureOfInterest (linked by hasFeatureOfInterest) of this Observation."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/observes",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Sensor"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/ObservableProperty"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "Relation between a Sensor and an ObservableProperty that it is capable of sensing."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "observes"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "Relation between a Sensor and an ObservableProperty that it is capable of sensing."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/phenomenonTime",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://schema.org/rangeIncludes" : [ {
"@id" : "http://www.w3.org/2006/time#TemporalEntity"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "The time that the Result of an Observation, Actuation or Sampling applies to the FeatureOfInterest. Not necessarily the same as the resultTime. May be an Interval or an Instant, or some other compound TemporalEntity."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "phenomenon time"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "The time that the Result of an Observation, Actuation or Sampling applies to the FeatureOfInterest. Not necessarily the same as the resultTime. May be an Interval or an Instant, or some other compound TemporalEntity."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/resultTime",
"@type" : [ "http://www.w3.org/2002/07/owl#DatatypeProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "The result time is the instant of time when the Observation, Actuation or Sampling activity was completed."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "result time"
} ],
"http://www.w3.org/2000/01/rdf-schema#range" : [ {
"@id" : "http://www.w3.org/2001/XMLSchema#dateTime"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "The result time is the instant of time when the Observation, Actuation or Sampling activity was completed."
} ]
}, {
"@id" : "http://www.w3.org/ns/sosa/usedProcedure",
"@type" : [ "http://www.w3.org/2002/07/owl#ObjectProperty" ],
"http://schema.org/domainIncludes" : [ {
"@id" : "http://www.w3.org/ns/sosa/Observation"
} ],
"http://www.w3.org/2000/01/rdf-schema#comment" : [ {
"@language" : "en",
"@value" : "A relation to link to a re-usable Procedure used in making an Observation, an Actuation, or a Sample, typically through a Sensor, Actuator or Sampler."
} ],
"http://www.w3.org/2000/01/rdf-schema#label" : [ {
"@language" : "en",
"@value" : "used procedure"
} ],
"http://www.w3.org/2004/02/skos/core#definition" : [ {
"@language" : "en",
"@value" : "A relation to link to a re-usable Procedure used in making an Observation, an Actuation, or a Sample, typically through a Sensor, Actuator or Sampler."
} ]
}, {
"@id" : "http://xmlns.com/foaf/0.1/Agent",
"@type" : [ "http://www.w3.org/2002/07/owl#Class" ]
}, {
"@id" : "http://xmlns.com/foaf/0.1/name",
"@type" : [ "http://www.w3.org/2002/07/owl#AnnotationProperty" ]
} ]

8
uploads/MetaTest.json Normal file
View file

@ -0,0 +1,8 @@
[ {
"@id" : "_:genid1",
"@type" : [ "http://xmlns.com/foaf/0.1/Agent" ],
"http://xmlns.com/foaf/0.1/name" : [ {
"@language" : "en",
"@value" : "W3C/OGC Spatial Data on the Web Working Group"
} ]
} ]

View file

@ -0,0 +1,13 @@
[ {
"@id" : "http://example.org/data/Observation/346344",
"@type" : [ "http://www.w3.org/2002/07/owl#NamedIndividual", "http://www.w3.org/ns/sosa/Observation" ],
"http://www.w3.org/ns/sosa/hasFeatureOfInterest" : [ {
"@id" : "http://www.w3.org/ns/sosa/'Office_temperature'"
} ],
"http://www.w3.org/ns/sosa/madeBySensor" : [ {
"@id" : "http://www.w3.org/ns/sosa/'DHT11'"
} ],
"http://www.w3.org/ns/sosa/observedProperty" : [ {
"@id" : "http://www.w3.org/ns/sosa/'air_temperature'"
} ]
}]

BIN
wallet/.DS_Store vendored

Binary file not shown.

View file

@ -1,67 +0,0 @@
const ChainUtil = require('../chain-util');
const { MINING_REWARD } = require('../config');
class CoinTransaction {
constructor() {
this.id = ChainUtil.id();
this.input = null;
this.outputs = [];
}
update(senderWallet, recipient, amount) {
const senderOutput = this.outputs.find(output => output.address === senderWallet.publicKey);
if (amount > senderOutput.amount) {
console.log(`Amount: ${amount} exceeds balance.`);
return;
}
senderOutput.amount = senderOutput.amount - amount;
this.outputs.push({ amount, address: recipient });
CoinTransaction.signCoinTransaction(this, senderWallet);
return this;
}
static CoinTransactionWithOutputs(senderWallet, outputs) {
const cointransaction = new this();
cointransaction.outputs.push(...outputs);
CoinTransaction.signCoinTransaction(cointransaction, senderWallet);
return cointransaction;
}
static newCoinTransaction(senderWallet, recipient, amount) {
if (amount > senderWallet.balance) {
console.log(`Amount: ${amount} exceeds balance.`);
return;
}
return CoinTransaction.CoinTransactionWithOutputs(senderWallet, [
{ amount: senderWallet.balance - amount, address: senderWallet.publicKey},
{ amount, address: recipient }]);
}
static rewardCoinTransaction(minerWallet, blockchainWallet) {
return CoinTransaction.CoinTransactionWithOutputs(blockchainWallet, [{
amount: MINING_REWARD, address: minerWallet.publicKey
}]);
}
static signCoinTransaction(cointransaction, senderWallet) {
cointransaction.input = {
timestamp: Date.now(),
amount: senderWallet.balance,
address: senderWallet.publicKey,
signature: senderWallet.sign(ChainUtil.hash(cointransaction.outputs))
}
}
static verifyCoinTransaction(cointransaction) {
return ChainUtil.verifySignature(
cointransaction.input.address,
cointransaction.input.signature,
ChainUtil.hash(cointransaction.outputs)
);
}
}
module.exports = CoinTransaction;

View file

@ -1,100 +0,0 @@
const ChainUtil = require('../chain-util');
class MetaDataTransaction {
constructor() {
this.id = null; // if there is a problem in the metadata transaction, change null with ChainUtil.id();
this.Signiture = null;
this.Name = null;
this.Geo = [];
this.IP_URL = null;
this.Topic_Token = null;
this.Permission = null;
this.RequestDetail = null;
this.OrgOwner = null;
this.DepOwner = null;
this.PrsnOwner = null;
this.MetaHash = null;
this.PaymentPerKbyte = null;
this.PaymentPerMinute = null;
this.Protocol = null;
this.MessageAttributes= {};
this.Interval = null;
this.FurtherDetails = null;
this.SSNmetadata = null;
// this.Geo = null;
// this.Std = null;
// this.name= null;
// this.MetaHash= null;
// this.file=null;
}
// update(senderWallet, Geo, URI, Name,Permission, OrgOwner, SSNmetadata) {
// this.Geo = Geo;
// this.URI = URI;
// this.Name = Name;
// this.Permission = Permission;
// this.OrgOwner = OrgOwner;
// this.PrsnOwner = senderWallet.publicKey;
// this.MetaHash = ChainUtil.hash(SSNmetadata);
// this.SSNmetadata = SSNmetadata;
// MetaDatatransaction.signMetaDataTransaction(this, senderWallet);
// return this;
// }
static MetaDataTransactionWithIoT(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Intrval, FurtherDetails, SSNmetadata) {
const metaDataTransaction = new this();
metaDataTransaction.id = ChainUtil.id();
metaDataTransaction.Name = Name;
metaDataTransaction.Geo = Geo;
metaDataTransaction.IP_URL = IP_URL;
metaDataTransaction.Topic_Token = Topic_Token;
metaDataTransaction.Permission = Permission;
metaDataTransaction.RequestDetail = RequestDetail
metaDataTransaction.OrgOwner = OrgOwner;
metaDataTransaction.DepOwner = DepOwner;
metaDataTransaction.PrsnOwner = PrsnOwner;
metaDataTransaction.PaymentPerKbyte = PaymentPerKbyte ;
metaDataTransaction.PaymentPerMinute = PaymentPerMinute;
metaDataTransaction.Protocol = Protocol;
metaDataTransaction.MessageAttributes = MessageAttributes;
metaDataTransaction.MessageAttributes['DeviceID'] = metaDataTransaction.id;
metaDataTransaction.MessageAttributes['DeviceName'] = Name;
metaDataTransaction.MessageAttributes['Sensors'] =[{"SensorName":"","Value":"" , "Unit":""}];
metaDataTransaction.MessageAttributes['TimeStamp'] = "";
metaDataTransaction.Interval = Intrval;
metaDataTransaction.FurtherDetails = FurtherDetails;
metaDataTransaction.SSNmetadata = SSNmetadata;
metaDataTransaction.MetaHash = ChainUtil.hash(SSNmetadata);
MetaDataTransaction.signMetaDataTransaction(metaDataTransaction, senderWallet);
return metaDataTransaction;
}
static newMetaDataTransaction(senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval, FurtherDetails, SSNmetadata){
return MetaDataTransaction.MetaDataTransactionWithIoT(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval, FurtherDetails, SSNmetadata
);
}
static signMetaDataTransaction (metaDataTransaction, senderWallet) {
metaDataTransaction.Signiture = {
timestamp: Date.now(),
address: senderWallet.publicKey,
signature: senderWallet.sign(ChainUtil.hash(metaDataTransaction.SSNmetadata))
}
}
static verifyMetaDataTransaction(metaDataTransaction) {
return ChainUtil.verifySignature(
metaDataTransaction.Signiture.address,
metaDataTransaction.Signiture.signature,
ChainUtil.hash(metaDataTransaction.SSNmetadata)
);
}
}
module.exports = MetaDataTransaction;

View file

@ -1,8 +1,7 @@
const ChainUtil = require('../chain-util'); const ChainUtil = require('../chain-util');
const CoinTransaction = require('./CoinTransaction'); const Transaction = require('./transaction');
const { INITIAL_BALANCE } = require('../config'); const { INITIAL_BALANCE } = require('../config');
const MetaDataTransaction = require('./MetaDataTransaction'); const Metadata = require('./metadata');
const transactionPool = require('./transaction-pool');
class Wallet { class Wallet {
constructor() { constructor() {
@ -21,49 +20,57 @@ class Wallet {
return this.keyPair.sign(dataHash); return this.keyPair.sign(dataHash);
} }
createCoinTransaction(recipient, amount, blockchain, transactionPool) { createTransaction(recipient, amount, blockchain, transactionPool) {
// this.balance = this.calculateBalance(blockchain); this.balance = this.calculateBalance(blockchain);
if (amount > this.balance) { if (amount > this.balance) {
console.log(`Amount: ${amount} exceceds current balance: ${this.balance}`); console.log(`Amount: ${amount} exceceds current balance: ${this.balance}`);
return; return;
} }
let cointransaction = transactionPool.existingPaymentTransaction(this.publicKey); let transaction = transactionPool.existingTransaction(this.publicKey);
if (transaction) {
transaction.update(this, recipient, amount);
} else {
transaction = Transaction.newTransaction(this, recipient, amount);
transactionPool.updateOrAddTransaction(transaction);
}
if (cointransaction) { return transaction;
cointransaction.update(this, recipient, amount);
} else { //this should be the original one
//just for test i make the transaction not to update if the sender is the same
cointransaction = CoinTransaction.newCoinTransaction(this, recipient, amount);
transactionPool.updateOrAddPaymentTransaction(cointransaction);
}
return cointransaction;
} }
createMetaDataTransaction(Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval, FurtherDetails, SSNmetadata, transactionPool){
/* let metaData = metaDataPool.existingMetaData(this.publicKey);
if (metaData) {
metaData.update(this, Geo, Std, Name,MetaHash,file);
} else {*/
const metaDataTransaction= MetaDataTransaction.newMetaDataTransaction(this, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes,Interval, FurtherDetails, SSNmetadata);
transactionPool.updateOrAddMetaDataTransaction(metaDataTransaction);
//}
return metaDataTransaction;
}
createMetadata(Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,
PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval,
FurtherDetails, SSNmetadata, transactionPool){
//let metadata = transactionPool.existingMetadata(this.publicKey);
// if (metaData) {
// metadata.update(this, Geo, Std, Name,MetaHash,file);
// } else {*/
let metadata= Metadata.newMetadata(this, Name,Geo ,IP_URL , Topic_Token, Permission,
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute,
Protocol, MessageAttributes,Interval, FurtherDetails, SSNmetadata);
transactionPool.AddMetadata(metadata);
//}
return metadata;
}
calculateBalance(blockchain) { calculateBalance(blockchain) {
let balance = this.balance; let balance = this.balance;
let cointransactions = []; let transactions = [];
blockchain.chain.forEach(block => block.data.forEach(cointransaction => { blockchain.chain.forEach(block => block.data.forEach(transaction => {
cointransactions.push(cointransaction); transactions.push(transaction);
})); }));
console.log("transactions of balance")
const walletInputTs = cointransactions console.log(transactions);
.filter(cointransaction => cointransaction.input.address === this.publicKey); const PaymentTransactions = transactions[0];
console.log("Payment transactions ")
console.log(PaymentTransactions);
const walletInputTs = PaymentTransactions.filter(transaction => transaction.input.address === this.publicKey);
let startTime = 0; let startTime = 0;
@ -76,9 +83,9 @@ class Wallet {
startTime = recentInputT.input.timestamp; startTime = recentInputT.input.timestamp;
} }
cointransactions.forEach(cointransaction => { PaymentTransactions.forEach(transaction => {
if (cointransaction.input.timestamp > startTime) { if (transaction.input.timestamp > startTime) {
cointransaction.outputs.find(output => { transaction.outputs.find(output => {
if (output.address === this.publicKey) { if (output.address === this.publicKey) {
balance += output.amount; balance += output.amount;
} }
@ -96,4 +103,5 @@ class Wallet {
} }
} }
module.exports = Wallet; module.exports = Wallet;

View file

@ -7,7 +7,7 @@ describe('Wallet', () => {
let wallet, tp, bc; let wallet, tp, bc;
beforeEach(() => { beforeEach(() => {
wallet = new Wallet(); wallet = new Wallet();
tp = new TransactionPool(); tp = new TransactionPool();
bc = new Blockchain(); bc = new Blockchain();
}); });
@ -18,16 +18,12 @@ describe('Wallet', () => {
beforeEach(() => { beforeEach(() => {
sendAmount = 50; sendAmount = 50;
recipient = 'r4nd0m-4ddr355'; recipient = 'r4nd0m-4ddr355';
Geo = 20; transaction = wallet.createTransaction(recipient, sendAmount, bc, tp);
Std = 9014;
Name = 'temp';
MetaHash = '123abcd';
transaction = wallet.createCoinTransaction(recipient, sendAmount,Geo, Std, Name,MetaHash, bc, tp);
}); });
describe('and doing the same transaction', () => { describe('and doing the same transaction', () => {
beforeEach(() => { beforeEach(() => {
wallet.createCoinTransaction(recipient, sendAmount,Geo, Std, Name,MetaHash, bc, tp); wallet.createTransaction(recipient, sendAmount, bc, tp);
}); });
it('doubles the `sendAmount` subtracted from the wallet balance', () => { it('doubles the `sendAmount` subtracted from the wallet balance', () => {
@ -50,9 +46,9 @@ describe('Wallet', () => {
addBalance = 100; addBalance = 100;
repeatAdd = 3; repeatAdd = 3;
for (let i=0; i<repeatAdd; i++) { for (let i=0; i<repeatAdd; i++) {
senderWallet.createCoinTransaction(wallet.publicKey, addBalance,Geo, Std, Name,MetaHash, bc, tp); senderWallet.createTransaction(wallet.publicKey, addBalance, bc, tp);
} }
bc.addBlock(tp.paymenttransactions); bc.addBlock(tp.transactions);
}); });
it('calculates the balance for blockchain transactions matching the recipient', () => { it('calculates the balance for blockchain transactions matching the recipient', () => {
@ -70,15 +66,15 @@ describe('Wallet', () => {
tp.clear(); tp.clear();
subtractBalance = 60; subtractBalance = 60;
recipientBalance = wallet.calculateBalance(bc); recipientBalance = wallet.calculateBalance(bc);
wallet.createCoinTransaction(senderWallet.publicKey, subtractBalance,20,9014,'temp','123abc', bc, tp); wallet.createTransaction(senderWallet.publicKey, subtractBalance, bc, tp);
bc.addBlock(tp.paymenttransactions); bc.addBlock(tp.transactions);
}); });
describe('and the sender sends another transaction to the recipient', () => { describe('and the sender sends another transaction to the recipient', () => {
beforeEach(() => { beforeEach(() => {
tp.clear(); tp.clear();
senderWallet.createCoinTransaction(wallet.publicKey, addBalance, 20,9014,'temp','123abc',bc, tp); senderWallet.createTransaction(wallet.publicKey, addBalance, bc, tp);
bc.addBlock(tp.paymenttransactions); bc.addBlock(tp.transactions);
}); });
it('calculate the recipient balance only using transactions since its most recent one', () => { it('calculate the recipient balance only using transactions since its most recent one', () => {

88
wallet/metadata.js Normal file
View file

@ -0,0 +1,88 @@
const ChainUtil = require('../chain-util');
class Metadata {
constructor() {
this.id = null;
this.Signiture = null;
this.Name = null;
this.Geo = null;
// this.GeospatialLocation = [];
// this.Owenership = null;
// this.Cost = null;
// this.Identifications = null;
// this.Integration = null;
this.IP_URL = null;
this.Topic_Token = null;
this.Permission = null;
this.RequestDetail = null;
this.OrgOwner = null;
this.DepOwner = null;
this.PrsnOwner = null;
this.MetaHash = null;
this.PaymentPerKbyte = null;
this.PaymentPerMinute = null;
this.Protocol = null;
this.MessageAttributes= {};
this.Interval = null;
this.FurtherDetails = null;
this.SSNmetadata = null;
}
static MetadataOfIoTDevice(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Intrval, FurtherDetails, SSNmetadata) {
const metadata = new this();
metadata.id = ChainUtil.id();
metadata.Name = Name;
metadata.Geo = Geo;
metadata.IP_URL = IP_URL;
metadata.Topic_Token = Topic_Token;
metadata.Permission = Permission;
metadata.RequestDetail = RequestDetail
metadata.OrgOwner = OrgOwner;
metadata.DepOwner = DepOwner;
metadata.PrsnOwner = PrsnOwner;
metadata.PaymentPerKbyte = PaymentPerKbyte ;
metadata.PaymentPerMinute = PaymentPerMinute;
metadata.Protocol = Protocol;
metadata.MessageAttributes = MessageAttributes;
// metadata.MessageAttributes['DeviceID'] = metadata.id;
// metadata.MessageAttributes['DeviceName'] = Name;
// metadata.MessageAttributes['Sensors'] =[{"SensorName":"","Value":"" , "Unit":""}];
// metadata.MessageAttributes['TimeStamp'] = "";
metadata.Interval = Intrval;
metadata.FurtherDetails = FurtherDetails;
metadata.SSNmetadata = SSNmetadata;
metadata.MetaHash = ChainUtil.hash(SSNmetadata);
Metadata.signMetadata(metadata, senderWallet);
return metadata;
}
static newMetadata(senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail,
OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes,
Interval, FurtherDetails, SSNmetadata){
return Metadata.MetadataOfIoTDevice(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission,
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol,
MessageAttributes, Interval, FurtherDetails, SSNmetadata
);
}
static signMetadata (metadata, senderWallet) {
metadata.Signiture = {
timestamp: Date.now(),
address: senderWallet.publicKey,
signature: senderWallet.sign(ChainUtil.hash(metadata.SSNmetadata))
}
}
static verifyMetadata(metadata) {
return ChainUtil.verifySignature(
metadata.Signiture.address,
metadata.Signiture.signature,
ChainUtil.hash(metadata.SSNmetadata)
);
}
}
module.exports = Metadata;

109
wallet/metadata.test.js Normal file
View file

@ -0,0 +1,109 @@
const Transaction = require('./transaction');
const Metadata = require('./metadata');
const Wallet = require('./index');
const { MINING_REWARD } = require('../config');
describe('Transaction & Metadata', () => {
let transaction, metadata, wallet, recipient, amount,
senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission,
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte,
PaymentPerMinute, Protocol, MessageAttributes, Interval,
FurtherDetails, SSNmetadata;
beforeEach(() => {
wallet = new Wallet();
amount = 50;
recipient = 'r3c1p13nt';
senderWallet = new Wallet();
Name = 'IoT_Lab_Temp_Sensor'
Geo = [1.045,0.0135]
IP_URL = 'www.IoT-locationbar.com/sensors/temp'
Topic_Token = 'ACCESS_TOKEN'
Permission = 'Public'
RequestDetail = 'Null'
OrgOwner = 'Swinburne_University'
DepOwner = 'Computer_Science'
PrsnOwner = 'Anas_Dawod'
PaymentPerKbyte = 10
PaymentPerMinute = 5
Protocol = 'MQTT'
MessageAttributes = 'null'
Interval = 10
FurtherDetails = 'null'
SSNmetadata = 'null'
transaction = Transaction.newTransaction(wallet, recipient, amount);
metadata = Metadata.newMetadata(senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission,
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte,
PaymentPerMinute, Protocol, MessageAttributes, Interval,
FurtherDetails, SSNmetadata)
});
it('outputs the `amount` subtracted from the wallet balance', () => {
expect(transaction.outputs.find(output => output.address === wallet.publicKey).amount)
.toEqual(wallet.balance - amount);
});
it('outputs the `amount` added to the recipient', () => {
expect(transaction.outputs.find(output => output.address === recipient).amount)
.toEqual(amount);
});
it('inputs the balance of the wallet', () => {
expect(transaction.input.amount).toEqual(wallet.balance);
});
it('validates a valid transaction', () => {
expect(Transaction.verifyTransaction(transaction)).toBe(true);
});
it('validates a valid metadata', () => {
expect(Metadata.verifyMetadata(metadata)).toBe(true);
});
it('invalidates a corrupt transaction', () => {
transaction.outputs[0].amount = 50000;
expect(Transaction.verifyTransaction(transaction)).toBe(false);
});
describe('transacting with an amount that exceeds the balance', () => {
beforeEach(() => {
amount = 50000;
transaction = Transaction.newTransaction(wallet, recipient, amount);
});
it('does not create the transaction', () => {
expect(transaction).toEqual(undefined);
});
});
describe('and updating a transaction', () => {
let nextAmount, nextRecipient;
beforeEach(() => {
nextAmount = 20;
nextRecipient = 'n3xt-4ddr355';
transaction = transaction.update(wallet, nextRecipient, nextAmount);
});
it(`subtracts the next amount from the sender's output`, () => {
expect(transaction.outputs.find(output => output.address === wallet.publicKey).amount)
.toEqual(wallet.balance - amount - nextAmount);
});
it('outputs an amount for the next recipient', () => {
expect(transaction.outputs.find(output => output.address === nextRecipient).amount)
.toEqual(nextAmount);
});
});
describe('creating a reward transaction', () => {
beforeEach(() => {
transaction = Transaction.rewardTransaction(wallet, Wallet.blockchainWallet());
});
it(`reward the miner's wallet`, () => {
expect(transaction.outputs.find(output => output.address === wallet.publicKey).amount)
.toEqual(MINING_REWARD);
});
});
});

View file

@ -1,118 +1,73 @@
const PaymntTransaction = require('./CoinTransaction'); const Transaction = require('../wallet/transaction');
const MetaDataTransaction = require('./MetaDataTransaction'); const Metadata = require('../wallet/metadata')
//const CompTransaction = require('./CompTransaction');
//const IntegrationTransaction = require('./IntegrationTransaction');
const { MaxNumOfPaymentTransactions, MaxNumOfMetadataTransactions,
MaxNumOfCompTransactions, MaxNumOfIntegrationTransactions}
= require('../config');
class TransactionPool { class TransactionPool {
constructor() { constructor() {
this.paymenttransactions = []; this.transactions = [];
this.metaDataTransactions =[]; this.metadataS =[];
this.comptransactions = [];
this.integrationTransactions =[];
} }
updateOrAddPaymentTransaction(paymenttransaction) {
let paymenttransactionWithId = this.paymenttransactions.find(t => updateOrAddTransaction(transaction) {
t.id === paymenttransaction.id); let transactionWithId = this.transactions.find(t => t.id === transaction.id);
if (paymenttransactionWithId) {
this.paymenttransactions[this.paymenttransactions.indexOf if (transactionWithId) {
(paymenttransactionWithId)] = paymenttransaction; this.transactions[this.transactions.indexOf(transactionWithId)] = transaction;
} else {
this.paymenttransactions.push(paymenttransaction);
}
}
updateOrAddMetaDataTransaction(metaDataTransaction) {
let metaDataTransactionWithId = this.metaDataTransactions.find(t =>
t.id === metaDataTransaction.id);
if (metaDataTransactionWithId) {
this.metaDataTransactions[this.metaDataTransactions.indexOf
(metaDataTransactionWithId)] = metaDataTransaction;
} else { } else {
this.metaDataTransactions.push(metaDataTransaction); this.transactions.push(transaction);
} }
} }
updateOrAddCompTransaction(comptransaction) {
let comptransactionWithId = this.comptransactions.find(t => AddMetadata(metadata) {
t.id === comptransaction.id); // let metadataWithId = this.metadataS.find(t => t.id === metadata.id);
if (comptransactionWithId) {
this.comptransactions[this.comptransactions.indexOf // if (metadataWithId) {
(comptransactionWithId)] = comptransaction; // this.metaDataS[this.metadataS.indexOf(metadataWithId)] = metadata;
} else { // } else {
this.comptransactions.push(comptransaction); this.metadataS.push(metadata);
} } // }
updateOrAddIntegrationTransaction(integrationTransaction) {
let integrationTransactionWithId = this.integrationTransaction.find(
t => t.id === integrationTransaction.id);
if (integrationTransactionWithId) {
this.integrationTransactions[this.integrationTransactions.indexOf
(integrationTransactionWithId)] = integrationTransaction;
} else {
this.integrationTransactions.push(integrationTransaction);
}
} }
existingPaymentTransaction(address) {
return this.paymenttransactions.find(t => existingTransaction(address) {
t.input.address === address); } return this.transactions.find(t => t.input.address === address);
existingMetaDataTransaction(address) { }
return this.metaDataTransactions.find(t =>
t.Signiture.address === address);} existingMetadata(address) {
existingCompTransaction(address) { return this.metadataS.find(t => t.Signiture.address === address);
return this.comptransactions.find(t => }
t.input.address === address); }
existingIntegrationTransaction(address) { validTransactions() {
return this.integrationTransactions.find(t => return this.transactions.filter(transaction => {
t.Signiture.address === address);} const outputTotal = transaction.outputs.reduce((total, output) => {
validPaymentTransactions() {
return this.paymenttransactions.filter(paymenttransaction => {
const outputTotal = paymenttransaction.outputs.reduce(
(total, output) => {
return total + output.amount; return total + output.amount;
}, 0); }, 0);
if (paymenttransaction.input.amount !== outputTotal) {
console.log(`Invalid transaction from if (transaction.input.amount !== outputTotal) {
${paymenttransaction.input.address}.`); console.log(`Invalid transaction from ${transaction.input.address}.`);
return;} return;
if (!PaymentTransaction.verifyPaymentTransaction( }
paymenttransaction)) {
console.log(`Invalid signature from if (!Transaction.verifyTransaction(transaction)) {
${paymenttransaction.input.address}.`); console.log(`Invalid signature from ${transaction.input.address}.`);
return;} return;
return paymenttransaction; }
return transaction;
}); });
} }
validMetaDataTransactions(){
if (!MetaDataTransaction.verifyMetaDataTransaction( validMetadataS(){
metaDataTransaction)) { return this.metadataS.filter(metadata => {
console.log(`Invalid signature from if (!Metadata.verifyMetadata(metadata)) {
${metaDataTransaction.Signiture.address}.`); console.log(`Invalid signature from ${metadata.Signiture.address}.`);
return; return;
} }
return metaDataTransaction; return metadata;
});
} }
validCompTransactions(){
if (!CompTransaction.verifyCompTransaction( clear() {
CompTransaction)) { this.transactions = [];
console.log(`Invalid signature from this.metadataS = [];
${CompTransaction.Signiture.address}.`);
return;
}
return compTransaction;
}
validIntegrationTransactions(){
if (!IntegrationTransaction.verifyIntegrationTransaction(
integrationTransaction)) {
console.log(`Invalid signature from
${integrationTransaction.Signiture.address}.`);
return;
}
return integrationTransaction;
}
clearAll() {
this.cointransactions = [];
this.metaDataTransactions = [];
this.comptransactions = [];
this.integrationTransactions = [];
} }
} }
module.exports = TransactionPool; module.exports = TransactionPool;

View file

@ -1,44 +1,72 @@
const TransactionPool = require('./transaction-pool'); const TransactionPool = require('./transaction-pool');
const Transaction = require('./Cointransaction'); const Transaction = require('./transaction');
const Metadata = require('./metadata')
const Wallet = require('./index'); const Wallet = require('./index');
const Blockchain = require('../blockchain'); const Blockchain = require('../blockchain');
describe('TransactionPool', () => { describe('TransactionPool', () => {
let tp, wallet, transaction, bc; let tp, wallet, transaction, metadata, bc;
beforeEach(() => { beforeEach(() => {
tp = new TransactionPool(); tp = new TransactionPool();
wallet = new Wallet(); wallet = new Wallet();
wallet2 =new Wallet();
bc = new Blockchain(); bc = new Blockchain();
transaction = wallet.createCoinTransaction('r4nd-4dr355', 30,20,9014,'temp','123abc', bc, tp); transaction = wallet.createTransaction('r4nd-4dr355', 30, bc, tp);
// senderWallet = 'address';
// Name = 'IoT_Lab_Temp_Sensor'
// Geo = [1.045,0.0135]
// IP_URL = 'www.IoT-locationbar.com/sensors/temp'
// Topic_Token = 'ACCESS_TOKEN'
// Permission = 'Public'
// RequestDetail = 'Null'
// OrgOwner = 'Swinburne_University'
// DepOwner = 'Computer_Science'
// PrsnOwner = 'Anas_Dawod'
// PaymentPerKbyte = 10
// PaymentPerMinute = 5
// Protocol = 'MQTT'
// MessageAttributes = 'null'
// Interval = 10
// FurtherDetails = 'null'
// SSNmetadata = 'null'
metadata = wallet.createMetadata('IoT_Lab_Temp_Sensor',[1.045,0.0135],"www.IoT-locationbar.com/sensors/temp" ,'ACCESS_TOKEN' , 'Public',
'Null', 'Swinburne_University', 'Computer_Science','Anas_Dawod', 10,
5, 'MQTT', 'null', 10,
'FurtherDetails', 'SSNmetadata',tp);
}); });
it('adds a transaction to the pool', () => { it('adds a transaction to the pool', () => {
expect(tp.paymenttransactions.find(t => t.id === transaction.id)).toEqual(transaction); expect(tp.transactions.find(t => t.id === transaction.id)).toEqual(transaction);
});
it('adds a metadata to the pool', () => {
expect(tp.metadataS.find(t => t.id === metadata.id)).toEqual(metadata);
}); });
it('updates a transaction in the pool', () => { it('updates a transaction in the pool', () => {
const oldTransaction = JSON.stringify(transaction); const oldTransaction = JSON.stringify(transaction);
const newTransaction = transaction.update(wallet, 'foo-4ddr355', 40,20,9014,'temp','123abc'); const newTransaction = transaction.update(wallet, 'foo-4ddr355', 40);
tp.updateOrAddPaymentTransaction(newTransaction); tp.updateOrAddTransaction(newTransaction);
expect(JSON.stringify(tp.paymenttransactions.find(t => t.id === newTransaction.id))) expect(JSON.stringify(tp.transactions.find(t => t.id === newTransaction.id)))
.not.toEqual(oldTransaction); .not.toEqual(oldTransaction);
}); });
it('clears transactions', () => { it('clears transactions and metadata', () => {
tp.clear(); tp.clear();
expect(tp.paymenttransactions).toEqual([]); expect(tp.transactions).toEqual([]);
expect(tp.metadataS).toEqual([]);
}); });
describe('mixing valid and corrupt transactions', () => { describe('mixing valid and corrupt transactions', () => {
let validTransactions; let validTransactions;
beforeEach(() => { beforeEach(() => {
validTransactions = [...tp.paymenttransactions]; validTransactions = [...tp.transactions];
for (let i=0; i<6; i++) { for (let i=0; i<6; i++) {
wallet = new Wallet(); wallet = new Wallet();
transaction = wallet.createCoinTransaction('r4nd-4dr355', 30,20,9014,'temp','123abc', bc, tp); transaction = wallet.createTransaction('r4nd-4dr355', 30, bc, tp);
if (i%2==0) { if (i%2==0) {
transaction.input.amount = 99999; transaction.input.amount = 99999;
} else { } else {
@ -48,7 +76,7 @@ describe('TransactionPool', () => {
}); });
it('shows a difference between valid and corrupt transactions', () => { it('shows a difference between valid and corrupt transactions', () => {
expect(JSON.stringify(tp.paymenttransactions)).not.toEqual(JSON.stringify(validTransactions)); expect(JSON.stringify(tp.transactions)).not.toEqual(JSON.stringify(validTransactions));
}); });
it('grabs valid transactions', () => { it('grabs valid transactions', () => {

69
wallet/transaction.js Normal file
View file

@ -0,0 +1,69 @@
const ChainUtil = require('../chain-util');
const { MINING_REWARD } = require('../config');
class Transaction {
constructor() {
this.id = ChainUtil.id();
this.input = null;
this.outputs = [];
}
update(senderWallet, recipient, amount) {
const senderOutput = this.outputs.find(output => output.address === senderWallet.publicKey);
if (amount > senderOutput.amount) {
console.log(`Amount: ${amount} exceeds balance.`);
return;
}
senderOutput.amount = senderOutput.amount - amount;
this.outputs.push({ amount, address: recipient });
Transaction.signTransaction(this, senderWallet);
return this;
}
static transactionWithOutputs(senderWallet, outputs) {
const transaction = new this();
transaction.outputs.push(...outputs);
Transaction.signTransaction(transaction, senderWallet);
return transaction;
}
static newTransaction(senderWallet, recipient, amount) {
if (amount > senderWallet.balance) {
console.log(`Amount: ${amount} exceeds balance.`);
return;
}
return Transaction.transactionWithOutputs(senderWallet, [
{ amount: senderWallet.balance - amount, address: senderWallet.publicKey },
{ amount, address: recipient }
]);
}
static rewardTransaction(minerWallet, blockchainWallet) {
return Transaction.transactionWithOutputs(blockchainWallet, [{
amount: MINING_REWARD, address: minerWallet.publicKey
}]);
}
static signTransaction(transaction, senderWallet) {
transaction.input = {
timestamp: Date.now(),
amount: senderWallet.balance,
address: senderWallet.publicKey,
signature: senderWallet.sign(ChainUtil.hash(transaction.outputs))
}
}
static verifyTransaction(transaction) {
return ChainUtil.verifySignature(
transaction.input.address,
transaction.input.signature,
ChainUtil.hash(transaction.outputs)
);
}
}
module.exports = Transaction;

View file

@ -1,4 +1,4 @@
const Transaction = require('./Cointransaction'); const Transaction = require('./transaction');
const Wallet = require('./index'); const Wallet = require('./index');
const { MINING_REWARD } = require('../config'); const { MINING_REWARD } = require('../config');