const bcrypt = require("bcrypt"); const fs = require("fs-extra"); const glob = require("glob"); const jwt = require("jwt-simple"); const axios = require("axios"); const path = require("path"); const conf = require(`${process.env.dirtown}/conf.json`); const Odmdb = require("./Odmdb.js"); // lowercase 1st letter is normal const towns = require("./Towns.js"); const pagans = require("./Pagans.js"); /* Blockchain manager * Manage network directory of nations and towns * read Blockchain and search, * submit a transaction (now) or contract (futur) to store from userA.pubkey to userB.pubkey a number of AXESS * mine to be able to register a block and create AXESS * manage APIXP rules 20 M APIXP 1AXESS = 1 block validation * manage contract = action if something appened validate by a proof of work */ const Nations = {}; Nations.init = () => { console.group("init Nations"); }; Nations.chaintown = (nationId, townId) => { /** * if not already exist Add a requested town into conf.towns.push({ "townId": "wall", "nationId": "ants", "dns": "wall-ants.ndda.fr" }) */ }; Nations.updateobjectsfromfreshesttown = (dnstownlist, objectidx) => { /** * Get lasttime update per apxtrib object then choose the latest source and update local town * if an item exist localy and does not from the town requested * @Param {array} dnstownlist list of dns to get latest data * @Param {object} objectidx objectnme:idxfile {agans:"alias_all.json",...} * @return create/update nationchains/pagans town nation */ const localversion = {}; const objlist = Object.keys(objectidx); objlist.forEach((o) => { let objconf = { name: o, schema: `adminapi/schema/${o}.jsons`, lastupdate: -1, }; if (fs.existsSync(`${conf.dirapi}/nationchains/${o}/conf.json`)) { objconf = fs.readJsonSync(`${conf.dirapi}/nationchains/${o}/conf.json`); } else { fs.outputJsonSync(`${conf.dirapi}/nationchains/${o}/conf.json`, objconf); } localversion[o] = [conf.dns[0], objconf.lastupdate]; }); //console.log(localversion); for (let t = 0; t < dnstownlist.length; t++) { if (conf.townId != dnstownlist[t].townId) { // to avoid update itself let promiseconf = []; let objecttotest = []; objlist.forEach((o) => { //console.log(`https://${dnstownlist[t].dns}/nationchains/${o}/conf.json`); objecttotest.push(o); promiseconf.push( axios.get(`https://${dnstownlist[t].dns}/nationchains/${o}/conf.json`) ); }); Promise.all(promiseconf) .then((reps) => { let promiseidx = []; let objecttoupdate = []; let objlastupdate = []; for (let i = 0; i < objecttotest.length; i++) { if ( parseInt(reps[i].data.lastupdate) > parseInt(localversion[reps[i].data.name][1]) ) { // add promise to get data /*console.log( `https://${dnstownlist[t].dns}/nationchains/${ reps[i].data.name }/idx/${objectidx[reps[i].data.name]}` );*/ objecttoupdate.push(objecttotest[i]); objlastupdate.push(reps[i].data.lastupdate); promiseidx.push( axios.get( `https://${dnstownlist[t].dns}/nationchains/${ reps[i].data.name }/idx/${objectidx[reps[i].data.name]}` ) ); } } Promise.all(promiseidx) .then((rets) => { for (let j = 0; j < objecttoupdate.length; j++) { Odmdb.updatefromidxall( objecttoupdate[j], objectidx[objecttoupdate[j]], rets[j].data, objlastupdate[j] ); } }) .catch((err) => { console.log("ERR get idx data"); console.log(err); }); }) .catch((err) => { console.log("ERR get conf lastupdate"); console.log(err); }); } } return {status:200,ref:"Nations",msg:"updated",data:{}}; }; Nations.synchronizeold = () => { /* Run process to communicate with a list of towns to update network and transaction */ //update himself then send to other information if (process.env.NODE_ENV != "prod") { // Not concerned return {}; } const initcurrentinstance = { fixedIP: "", lastblocknumber: 0, firsttimeupdate: 0, lastimeupdate: 0, positifupdate: 0, negatifupdate: 0, pubkeyadmin: "", tribeids: [], logins: [], knowninstance: [], }; let currentinstance = initcurrentinstance; try { currentinstance = fs.readFileSync( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/${conf.rootURL}`, "utf-8" ); } catch (err) { console.log("first init"); } const loginsglob = fs.readJsonSync(`${conf.tmp}/loginsglob.json`, "utf-8"); currentinstance.logins = Object.keys(loginsglob); currentinstance.tribeids = [...new Set(Object.values(loginsglob))]; currentinstance.instanceknown = glob.Sync( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/*` ); //Save it fs.outputJsonSync( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/${conf.rootURL}`, currentinstance ); // proof of work // try to find a key based on last block with difficulty // if find then send to all for update and try to get token // in any case rerun Nations.synchronize() currentinstance.instanceknown.forEach((u) => { if (u != conf.rootURL) { //send currentinstance info and get back state of axios .post(`https://${u}/nationchains/push`, currentinstance) .then((rep) => { newdata = rep.payload.moreinfo; //Available update info fs.readJson( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/${u}`, (err, data) => { if (err) { data.negatifupdate += 1; data.lasttimeupdate = Date.now(); } else { data.positifupdate += 1; data.lastimeupdate = Date.now(); data.tribeids = newdata.tribeids; data.logins = newdata.logins; data.lastblocknumber = newdata.lastblocknumber; newdata.knowninstance.forEach((k) => { if (!data.knowninstance.includes(k)) { data.knowninstance.push(k); //init the domain for next update initcurrentinstance.firsttimeupdate = Date.now(); fs.outputJson( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/${k}`, initcurrentinstance, "utf-8" ); } }); } //save with info fs.outputJson( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/${u}`, data ); } ); }) .catch((err) => { //Not available data.negatifupdate += 1; data.lasttimeupdate = Date.now(); fs.outputJson( `${conf.tribes}/${conf.mayorId}/nationchains/nodes/${u}`, data ); }); } }); }; Nations.create = (conf) => { /* @conf from a nationchains/socialworld/setup/townSetup {object, nationId, townId, dns} @return */ const res = {}; if (conf.object == "towns") { Odmdb.create("nationchains/socialworld/objects", "towns", conf); } const nations = fs.readJsonSync( "./nationchains/nations/idx/nationId_all.json" ); if (!ObjectKeys(nations).includes(conf.nationId)) { res.status = 404; res.info = `your nationId ${conf.nationId} does not exist you have to choose an existing one`; return res; } const towns = fs.readJsonSync("./nationchains/towns/idx/townId_all.json"); if (towns[conf.nationId].includes(conf.townId)) { res.status = 409; res.info = `This conf.townId already exist you have to find a unique town name`; return res; } const towndata = { uuid: conf.townId, nationid: conf.nationId, url: `${conf.townId}.${conf.nationId}.${conf.dns}`, status: conf.dns == "unchain" ? "unchain" : "tochain", }; const metatown = fs.readJsonSync( "./nationchains/socialworld/metaobject/towns.json" ); Odmdb.add(objectpath, towns, metatown, towndata); fs.outputJsonSync( `./nationchains/socialworld/objects/towns/${townId}.json`, towndata ); res.status = 200; res.info = `${townId} create for ${nationId} nation`; return res; }; module.exports = Nations;