demo version

This commit is contained in:
Josip Milovac 2023-07-13 11:32:02 +10:00
parent fbb282a801
commit 672d6daa8e
125 changed files with 17918 additions and 1481 deletions

View file

@ -30,7 +30,6 @@
const express = require('express');
const bodyParser = require('body-parser');
const P2pServer = require('../p2p-server');
const BlockchainProp = require('../network/blockchain-prop');
const QueryEngine = require('@comunica/query-sparql-rdfjs').QueryEngine;
const Blockchain = require('../blockchain/blockchain');
@ -38,7 +37,7 @@ const Miner = require('./miner');
'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 Config = require('../config');
const Config = require('../util/config');
const Payment = require('../blockchain/payment');
const Integration = require('../blockchain/integration');
@ -49,9 +48,7 @@ const Transaction = require('../blockchain/transaction');
const {
DEFAULT_PORT_MINER_API,
DEFAULT_PORT_MINER_CHAIN,
DEFAULT_PORT_MINER_TX_SHARE,
DEFAULT_PORT_MINER_TX_RECV
} = require('../constants');
} = require('../util/constants');
const CONFIGS_STORAGE_LOCATION = "./settings.json";
@ -84,9 +81,15 @@ const apiPort = config.get({
const blockchain = Blockchain.loadFromDisk(blockchainLocation);
const chainServer = new BlockchainProp("Chain-server", true, blockchain);
const miner = new Miner(blockchain, minerPublicKey);
const newTxCb = function (tx) {
console.log("new tx through cb");
miner.addTransaction(tx);
};
const chainServer = new BlockchainProp("Chain-server", blockchain, newTxCb);
chainServer.start(chainServerPort, minerPublicAddress, chainServerPeers);
const app = express();
@ -192,7 +195,7 @@ app.post('/sparql', (req, res) => {
req.body.query,
{
readOnly: true,
sources: blockchain.stores
sources: [blockchain.rdfSource()]
});
bindingsStream.on('data', (binding) => {
const pushing = {};
@ -216,351 +219,3 @@ app.post('/sparql', (req, res) => {
start()
});
/* ///////////////////////////////////////////////////////////Integration///////////////////////////////////////////////////////////
DistributedBrokers = ["mqtt.eclipse.org", "test.mosquitto.org","broker.hivemq.com"];
DistributedBrokersPorts = [1883,1883,1883];
function makeTopic(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
paymentAmount = [];
paymentAddress = [];
IoTDeviceAddress = [];
IoTApplicationAddress=[];
MassagiesRecived = [];
var MiddlewareClients =[];
MassageCounter =[];
StartSending = [];
MiddlewareTracking =[];
Durations = [];
Intervals = [];
i = 0;//RequestsIndex
app.post('/IoTdeviceIntegration-Control', (req, res) => {
const {IoTDeviceID,paymentTransactionID,Duration,Protocol}= req.body;
Durations.push(Duration);
MassageCounter.push(0)
MassagiesRecived.push(false);
data =bc.chain.map (a => a.data);
MetaANDTransFound = false;
for (let j= data.length-1; j>0; j-- ){
//this for loop load
//Blockchain and search for metadata and payment transaction that match
//the provided MetadataID and TransactionID
var metadata = data[j][1];
var transaction = data [j][0];
var pickedMetadata = lodash.find(metadata, x=>
x.id === IoTDeviceID);
var pickedTransction = lodash.find(transaction, x=>
x.id === paymentTransactionID);
if (pickedMetadata != null && pickedTransction !=null){
MetaANDTransFound = true;
break;} }
if (MetaANDTransFound){
//Loading the IoTdevice parameters in order to connect to it
var IoTDeviceBroker = pickedMetadata.IP_URL.toString();//mqtt broker
var IoTDeviceTopic = pickedMetadata.Topic_Token;// mqtt topic
paymentAmount.push(pickedTransction.outputs[1].amount);
paymentAddress.push(pickedTransction.outputs[1].address);
IoTDeviceAddress.push(pickedMetadata.Signiture.address);
IoTApplicationAddress.push(pickedTransction.input.address);
Intervals.push(pickedMetadata.Interval)
if (paymentAddress[i] == wallet.publicKey){
res.redirect('/IoTdataObtainingAndForward');}
else{
console.log("payment Address not match")}}
else{
console.log("Metadata or Transaction not found")
if (pickedMetadata == null){
console.log("metadata not found")}
if (pickedTransction == null){
console.log("Transaction not found")} }
MetaANDTransFound = false;
i++;
res.json("true");});
app.get ('/IoTdataObtainingAndForward', (req, res) => {
console.log (`transaction of IoT Application ${i} approved`)
BrokerRandomNumber = (Math.floor(
Math.random()*DistributedBrokers.length)+1)-1 //collect a random number to select a random broker
MiddlewareBroker = DistributedBrokers[BrokerRandomNumber];
MiddlewareTopic = makeTopic(5);// generate random topic
MiddlewarePort = DistributedBrokersPorts[BrokerRandomNumber];
//loading the configuration massage
configurationMessage = {"host/broker":MiddlewareBroker,
"topic":MiddlewareTopic,
"port":MiddlewarePort,
"duration":Duration} //add pk of the node connect to the IoT device and send the configuration massage
var IoTDeviceClient = mqtt.connect(IoTDeviceBroker);
MiddlewareClients.push(mqtt.connect(`mqtt://${MiddlewareBroker}`))
var MiddlewareClient = MiddlewareClients[i]
IoTDeviceClient.on("connect", ack => {
console.log("connected! to IoT Device Client");
IoTDeviceClient.subscribe(IoTDeviceTopic, err => {
console.log(err); });
IoTDeviceClient.publish(IoTDeviceTopic, JSON.stringify(
configurationMessage));});
IoTDeviceClient.on("error", err => {
console.log(err);});
IoTDeviceClient.on("message", (topic, message) => {
console.log(message.toString())
IoTDeviceClient.end(true)});
//connect the randomly choosed mqtt middlware broker to listen to the transmitted massagies
MiddlewareClient.on("connect", ack => {
console.log("connected!");
console.log(MiddlewareBroker)
StartSending.push(Date.now());
MiddlewareClient.subscribe(MiddlewareTopic, err => {
console.log(err); });});
MiddlewareTracking.push({index:i,
TrackingTopic:MiddlewareTopic}) //this used to track the connection in case there are multiple conection at the same time
MiddlewareClient.on("message", (topic, message) => {
//call back,
//will run each time a massage recived, I did it in a way if there are
//multiple connections, it will run for all the massagies, then truck the
//massagies by MiddlwareTracking Array
var MiddlewareFound = MiddlewareTracking.filter(function(item) {
return item.TrackingTopic == topic;});
console.log(MiddlewareFound);
console.log(message.toString());
MiddlewareIndex = MiddlewareFound[0].index// this is the index of the connection or the Middleware
console.log(MiddlewareIndex)
MassageCounter[MiddlewareIndex]++;//this used to track the number of recived massagies of each connection
console.log(Date.now()-StartSending[MiddlewareIndex])
if (Date.now() - StartSending[MiddlewareIndex] >=
(Durations[MiddlewareIndex]*1000)
-Intervals[MiddlewareIndex]*1000){
console.log("sending time finished")
if (MassageCounter[MiddlewareIndex] > 0.75*(
Durations[MiddlewareIndex]/Intervals[MiddlewareIndex])
){// which means most of massagies have been sent
console.log("massages recived")
MassagiesRecived[MiddlewareIndex] = true;}
if (MassagiesRecived[MiddlewareIndex]){// if massagies recived, pay the 10% as service fees
const PaymentTransaction = wallet.createPaymentTransaction(
NodeAddress,(0.1*paymentAmount[MiddlewareIndex]) , bc, tp);
p2pServer.broadcastPaymentTransaction(PaymentTransaction);
console.log("amount paid to the IoT device")
console.log(MiddlewareIndex)
MiddlewareClient = MiddlewareClients[MiddlewareIndex];
//disconnect the middleware mqtt broker
MiddlewareClient.end(true)}
else{// if massagies not recived, pay the IoT application back
res.redirect('/IoTapplicationCompensationTransaction')}};});
app.post('/IoTApplicationCompensationTransaction', (req, res) => {
const { Recipient_payment_address, Amount_of_money, Payment_method,
Further_details} = req.body;
if (Payment_method == "SensorCoin"){
const PaymentTransaction = wallet.createPaymentTransaction(
Recipient_payment_address, Amount_of_money, bc, tp);
p2pServer.broadcastPaymentTransaction(PaymentTransaction);
res.json("PaymentTransactionCreated");
}
else if (Payment_method == "Bitcoin") {
res.redirect('/BitcoinTransaction')
}
else if (Payment_method == "PayPal") {
res.redirect('/PayPalTransaction')
}
});
app.post ('/IoTapplicationCompensation', (req, res) => {
const PaymentTransaction = wallet.createPaymentTransaction(IoTApplicationAddress[MiddlewareIndex],
(paymentAmount[MiddlewareIndex]) , bc, tp);
p2pServer.broadcastPaymentTransaction(PaymentTransaction);
console.log("amount paid back to the IoT Application")
});
var IoTDeviceMassage ="test"
app.post('/integrateVirtual', (req, res) => {
const {IoTDeviceID,paymentTransactionID,Duration,Protocol}= req.body;
Durations.push(Duration);
MassageCounter.push(0)
MassagiesRecived.push(false);
data =bc.chain.map (a => a.data);
MetaANDTransFound = true;
// for (let j= 1; j<data.length; j++ ){// this for loop load the Blockchain and search for metadata and payment transaction that match the provided MetadataID and TransactionID
// var metadata = data[j][1];
// var transaction = data [j][0];
// var pickedMetadata = lodash.find(metadata, x=> x.id === IoTDeviceID); ////one thing to consider, what if the IoT device has multiple meatadata (updated metadata)??
// var pickedTransction = lodash.find(transaction, x=> x.id === paymentTransactionID);
// if (pickedMetadata != null && pickedTransction !=null){
// MetaANDTransFound = true;
// break;
// }
// }
if (MetaANDTransFound){
//Loading the IoTdevice parameters in order to connect to it
// var IoTDeviceBroker = pickedMetadata.IP_URL.toString();//mqtt broker
// var IoTDeviceTopic = pickedMetadata.Topic_Token;// mqtt topic
paymentAmount.push(10)//pickedTransction.outputs[1].amount);
paymentAddress.push("ADsf")//pickedTransction.outputs[1].address);
IoTDeviceAddress.push("fth")//pickedMetadata.Signiture.address);
IoTApplicationAddress.push("dtyuyf")//pickedTransction.input.address);
Intervals.push(10)//pickedMetadata.Interval)
var device = awsIot.device({
keyPath: './aws-iot-device-sdk/node_modules/certs/private.pem.key',
certPath: './aws-iot-device-sdk/node_modules/certs/certificate.pem.crt',
caPath: './aws-iot-device-sdk/node_modules/certs/RootCA1.pem',
clientId: 'arn:aws:iot:us-east-1:712303746524:thing/SecondVirtualIoTdevice',
host: 'a11joipjrff8s7-ats.iot.us-east-1.amazonaws.com'
});
//if (paymentAddress[i] == wallet.publicKey){
console.log (`transaction of IoT Application ${i} approved`) // add later the check if the amount is match with the required duration
BrokerRandomNumber = (Math.floor(Math.random()*DistributedBrokers.length)+1)-1 // collect a random number to select a random broker
MiddlewareBroker = DistributedBrokers[BrokerRandomNumber];
MiddlewareTopic = makeTopic(5);// generate random topic
MiddlewarePort = DistributedBrokersPorts[BrokerRandomNumber];
//loading the configuration massage
// configurationMessage = {"host/broker":MiddlewareBroker,"topic":MiddlewareTopic, "port":MiddlewarePort, "duration":Duration} // add pk of the node
// connect to the IoT device and send the configuration massage
// var IoTDeviceClient = mqtt.connect(IoTDeviceBroker);
// MiddlewareClients.push(mqtt.connect(`mqtt://${MiddlewareBroker}`))
// var MiddlewareClient = MiddlewareClients[i]
// IoTDeviceClient.on("connect", ack => {
// console.log("connected! to IoT Device Client");
// IoTDeviceClient.subscribe(IoTDeviceTopic, err => {
// console.log(err);
// });
// IoTDeviceClient.publish(IoTDeviceTopic, JSON.stringify(configurationMessage));
// });
// IoTDeviceClient.on("error", err => {
// console.log(err);
// });
// IoTDeviceClient.on("message", (topic, message) => {
// console.log(message.toString())
// IoTDeviceClient.end(true)
// });
// IoTDeviceClient.on("close", ack => {
// console.log("Disconnected from IoT Device Client");
// });
device
.on('connect', function() {
console.log('connect');
device.subscribe('/weather/data');// change it to a topic from the metadata
// device.publish('/weather/data', JSON.stringify({ test_data: 2}));
});
device
.on('message', function(topic, payload) {
// console.log('message', topic, payload.toString());
IoTDeviceMassage = payload.toString();
MiddlewareClient.publish(MiddlewareTopic,IoTDeviceMassage)
});
// connect the randomly choosed mqtt middlware broker to listen to the transmitted massagies
MiddlewareClients.push(mqtt.connect(`mqtt://${MiddlewareBroker}`))
var MiddlewareClient = MiddlewareClients[i]
MiddlewareClient.on("connect", ack => {
console.log("connected!");
console.log(MiddlewareBroker)
StartSending.push(Date.now());
MiddlewareClient.subscribe(MiddlewareTopic, err => {
console.log(err);
});
MiddlewareClient.publish(MiddlewareTopic,IoTDeviceMassage)
});
MiddlewareTracking.push({index:i, TrackingTopic:MiddlewareTopic})// this used to track the connection in case there are multiple conection at the same time
MiddlewareClient.on("message", (topic, message) => {// call back, will run each time a massage recived, I did it in a way if there are multiple connections, it will run for all the massagies, then we truck the massahies by MiddlwareTracking Array
console.log(message.toString());
var MiddlewareFound = MiddlewareTracking.filter(function(item) {
return item.TrackingTopic == topic;
});
console.log(MiddlewareFound);
MiddlewareIndex = MiddlewareFound[0].index;// this is the index of the connection or the Middleware
console.log(MiddlewareIndex);
MassageCounter[MiddlewareIndex]++;// this used to track the number of recived massagies of each connection
console.log(Date.now()-StartSending[MiddlewareIndex])
if (Date.now() - StartSending[MiddlewareIndex] >= (Durations[MiddlewareIndex]*1000)-Intervals[MiddlewareIndex]*1000){
console.log("sending time finished")
if (MassageCounter[MiddlewareIndex] > 0.75*(Durations[MiddlewareIndex]/Intervals[MiddlewareIndex])){// which means most of massagies have been sent
console.log("massages recived")
MassagiesRecived[MiddlewareIndex] = true;
}
if (MassagiesRecived[MiddlewareIndex]){// if massagies recived, pay the IoT device and substract 10% as service fees
const cointransaction = wallet.createCoinTransaction(IoTDeviceAddress[MiddlewareIndex],(paymentAmount[MiddlewareIndex]-0.1*paymentAmount[MiddlewareIndex]) , bc, tp);
p2pServer.broadcastCoinTransaction(cointransaction);
console.log("amount paid to the IoT device")
console.log(MiddlewareIndex)
MiddlewareClient = MiddlewareClients[MiddlewareIndex];// disconnect the middleware mqtt broker
MiddlewareClient.end(true)
}
else{// if massagies not recived, pay the ioT application back
const cointransaction = wallet.createCoinTransaction(IoTApplicationAddress[MiddlewareIndex],(paymentAmount[MiddlewareIndex]) , bc, tp);
p2pServer.broadcastCoinTransaction(cointransaction);
console.log("amount paid back to the IoT Application")
console.log(MiddlewareIndex)
MiddlewareClient = MiddlewareClients[MiddlewareIndex];// disconnect the middleware mqtt broker
MiddlewareClient.end(true)
}
}
});
// }
// else{
// console.log("payment Address not match")
// }
}
else{
console.log("Metadata or Transaction not found")
if (pickedMetadata == null){
console.log("metadata not found")
}
if (pickedTransction == null){
console.log("Transaction not found")
}
}
MetaANDTransFound = false;
i++;
//
// Device is an instance returned by mqtt.Client(), see mqtt.js for full
// documentation.
//
res.json("true");
});
});*/

View file

@ -5,6 +5,7 @@ const Integration = require('../blockchain/integration');
const SensorRegistration = require('../blockchain/sensor-registration');
const BrokerRegistration = require('../blockchain/broker-registration');
const Compensation = require('../blockchain/compensation');
const Transaction = require('../blockchain/transaction');
const ITERATIONS = 1;
@ -13,39 +14,45 @@ const STATE_INTERRUPTED = 1;
function mine(miner) {
if (miner.state !== STATE_RUNNING) {
this.startMine();
startMine(miner);
return;
}
const timestamp = Date.now();
const difficulty = Block.adjustDifficulty(miner.lastBlock, timestamp);
const txCount = miner.txs[Payment.name()].mining.length +
miner.txs[SensorRegistration.name()].mining.length +
miner.txs[BrokerRegistration.name()].mining.length +
miner.txs[Integration.name()].mining.length +
miner.txs[Compensation.name()].mining.length;
for (let i = 0; i < ITERATIONS; ++i) {
const hash = Block.hash(
timestamp,
miner.lastBlock.hash,
miner.reward,
miner.txs.payments.mining,
miner.txs.sensorRegistrations.mining,
miner.txs.brokerRegistrations.mining,
miner.txs.integrations.mining,
miner.txs.compensations.mining,
miner.txs[Payment.name()].mining,
miner.txs[SensorRegistration.name()].mining,
miner.txs[BrokerRegistration.name()].mining,
miner.txs[Integration.name()].mining,
miner.txs[Compensation.name()].mining,
miner.nonce,
difficulty);
if (hash.substring(0, difficulty) === '0'.repeat(difficulty)) {
//success
const endTime = process.hrtime.bigint();
console.log(`Mined a block of difficulty ${difficulty} in ${Number(endTime - miner.minedStartTime) / 1000000}ms`);
console.log(`Mined a block of difficulty ${difficulty} in ${Number(endTime - miner.minedStartTime) / 1000000}ms with ${txCount} txs`);
miner.blockchain.addBlock(new Block(
timestamp,
miner.lastBlock.hash,
hash,
miner.reward,
miner.txs.payments.mining,
miner.txs.sensorRegistrations.mining,
miner.txs.brokerRegistrations.mining,
miner.txs.integrations.mining,
miner.txs.compensations.mining,
miner.txs[Payment.name()].mining,
miner.txs[SensorRegistration.name()].mining,
miner.txs[BrokerRegistration.name()].mining,
miner.txs[Integration.name()].mining,
miner.txs[Compensation.name()].mining,
miner.nonce,
difficulty));
miner.state = STATE_INTERRUPTED;
@ -53,7 +60,11 @@ function mine(miner) {
return;
} else {
//failure
miner.nonce++;
if (miner.nonce === Number.MAX_SAFE_INTEGER) {
miner.nonce = Number.MIN_SAFE_INTEGER;
} else {
miner.nonce++;
}
}
}
setImmediate(() => { mine(miner) });
@ -68,13 +79,23 @@ function startMine(miner) {
miner.minedStartTime = process.hrtime.bigint();
//TODO make sure these transactions actually work as a collective instead of individually
miner.txs.payments.mining = [...miner.txs.payments.pool];
miner.txs.integrations.mining = [...miner.txs.integrations.pool];
miner.txs.sensorRegistrations.mining = [...miner.txs.sensorRegistrations.pool];
miner.txs.brokerRegistrations.mining = [...miner.txs.brokerRegistrations.pool];
miner.txs.compensations.mining = [...miner.txs.compensations.pool];
for (const type of Transaction.ALL_TYPES) {
const key = type.name();
miner.txs[key].mining = [];
for (const tx of miner.txs[key].pool) {
miner.txs[key].mining.push(tx);
if (!miner.blockchain.wouldBeValidBlock(miner.reward,
miner.txs[Payment.name()].mining,
miner.txs[SensorRegistration.name()].mining,
miner.txs[BrokerRegistration.name()].mining,
miner.txs[Integration.name()].mining,
miner.txs[Compensation.name()].mining)) {
miner.txs[key].mining.pop();
}
}
}
miner.nonce = 0;
miner.nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
miner.state = STATE_RUNNING;
mine(miner);
@ -84,7 +105,7 @@ function findTx(tx) {
return t => t.input === tx.input && t.counter === tx.counter;
}
function clearFromBlock(miner, txs, blockTxs) {
function clearFromBlock(txs, blockTxs) {
for (const tx of blockTxs) {
const foundIndex = txs.pool.findIndex(findTx(tx));
@ -109,28 +130,13 @@ class Miner {
}
});
this.txs = {
payments: {
this.txs = {};
for (const type of Transaction.ALL_TYPES) {
this.txs[type.name()] = {
pool: [],
mining: []
},
integrations: {
pool: [],
mining: []
},
sensorRegistrations: {
pool: [],
mining: []
},
brokerRegistrations: {
pool: [],
mining: []
},
compensations: {
pool: [],
mining: []
}
};
};
}
startMine(this);
}
@ -142,16 +148,7 @@ class Miner {
return;
}
let txs = null;
switch (tx.type) {
case Payment: txs = this.txs.payments; break;
case Integration: txs = this.txs.integrations; break;
case SensorRegistration: txs = this.txs.sensorRegistrations; break;
case BrokerRegistration: txs = this.txs.brokerRegistrations; break;
case Compensation: txs = this.txs.compensations; break;
default: throw new Error(`unknown tx type: ${tx.type.name()}`);
}
let txs = this.txs[tx.type.name()];
const foundIndex = txs.pool.findIndex(findTx(tx.transaction));
@ -166,11 +163,11 @@ class Miner {
}
onNewBlock(block) {
clearFromBlock(this, this.txs.payments, Block.getPayments(block));
clearFromBlock(this, this.txs.integrations, Block.getIntegrations(block));
clearFromBlock(this, this.txs.sensorRegistrations, Block.getSensorRegistrations(block));
clearFromBlock(this, this.txs.brokerRegistrations, Block.getBrokerRegistrations(block));
clearFromBlock(this, this.txs.compensations, Block.getCompensations(block));
clearFromBlock(this.txs[Payment.name()], Block.getPayments(block));
clearFromBlock(this.txs[Integration.name()], Block.getIntegrations(block));
clearFromBlock(this.txs[SensorRegistration.name()], Block.getSensorRegistrations(block));
clearFromBlock(this.txs[BrokerRegistration.name()], Block.getBrokerRegistrations(block));
clearFromBlock(this.txs[Compensation.name()], Block.getCompensations(block));
this.state = STATE_INTERRUPTED;