API(admin): generate, reshare and discard sinks
- generateSink: generates a sinkID for given group - reshareSink: regenerate the shares for given id and distribute - discardSink: discards the given sink id Note: All these APIs are admin-only
This commit is contained in:
parent
c8b70e3fec
commit
c5b43291ab
@ -519,6 +519,7 @@
|
||||
DUPLICATE_SIGNATURE: '017',
|
||||
SESSION_INVALID: '018',
|
||||
SESSION_EXPIRED: '019',
|
||||
INVALID_VALUE: '020',
|
||||
INVALID_TOKEN_NAME: '021',
|
||||
INVALID_NUMBER: '022',
|
||||
INVALID_TYPE: '023',
|
||||
@ -610,7 +611,7 @@
|
||||
exchangeAPI.getSink = function (service = serviceList.EXCHANGE) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!(service in serviceList))
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, 'service required', errorCode.INVALID_TYPE));
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, 'service required', errorCode.INVALID_VALUE));
|
||||
fetch_api('/get-sink?service=' + service)
|
||||
.then(result => {
|
||||
responseParse(result, false)
|
||||
@ -1557,6 +1558,99 @@
|
||||
})
|
||||
}
|
||||
|
||||
exchangeAPI.generateSink = function (group, floID, privKey) {
|
||||
if (!floCrypto.verifyPrivKey(privKey, floID))
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private Key", errorCode.INVALID_PRIVATE_KEY));
|
||||
if (floID !== DEFAULT.marketID)
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Access Denied", errorCode.ACCESS_DENIED));
|
||||
let request = {
|
||||
floID: floID,
|
||||
group: group,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
request.pubKey = floCrypto.getPubKeyHex(privKey);
|
||||
request.sign = signRequest({
|
||||
type: "generate_sink",
|
||||
group: group,
|
||||
timestamp: request.timestamp
|
||||
}, privKey);
|
||||
console.debug(request);
|
||||
|
||||
fetch_api('/generate-sink', {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(request)
|
||||
}).then(result => {
|
||||
responseParse(result, false)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
}).catch(error => reject(error))
|
||||
}
|
||||
|
||||
exchangeAPI.reshareSink = function (sinkID, floID, privKey) {
|
||||
if (!floCrypto.verifyPrivKey(privKey, floID))
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private Key", errorCode.INVALID_PRIVATE_KEY));
|
||||
if (floID !== DEFAULT.marketID)
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Access Denied", errorCode.ACCESS_DENIED));
|
||||
let request = {
|
||||
floID: floID,
|
||||
id: sinkID,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
request.pubKey = floCrypto.getPubKeyHex(privKey);
|
||||
request.sign = signRequest({
|
||||
type: "reshare_sink",
|
||||
id: sinkID,
|
||||
timestamp: request.timestamp
|
||||
}, privKey);
|
||||
console.debug(request);
|
||||
|
||||
fetch_api('/reshare-sink', {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(request)
|
||||
}).then(result => {
|
||||
responseParse(result, false)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
}).catch(error => reject(error))
|
||||
}
|
||||
|
||||
exchangeAPI.discardSink = function (sinkID, floID, privKey) {
|
||||
if (!floCrypto.verifyPrivKey(privKey, floID))
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Invalid Private Key", errorCode.INVALID_PRIVATE_KEY));
|
||||
if (floID !== DEFAULT.marketID)
|
||||
return reject(ExchangeError(ExchangeError.BAD_REQUEST_CODE, "Access Denied", errorCode.ACCESS_DENIED));
|
||||
let request = {
|
||||
floID: floID,
|
||||
id: sinkID,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
request.pubKey = floCrypto.getPubKeyHex(privKey);
|
||||
request.sign = signRequest({
|
||||
type: "discard_sink",
|
||||
id: sinkID,
|
||||
timestamp: request.timestamp
|
||||
}, privKey);
|
||||
console.debug(request);
|
||||
|
||||
fetch_api('/discard-sink', {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(request)
|
||||
}).then(result => {
|
||||
responseParse(result, false)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
}).catch(error => reject(error))
|
||||
}
|
||||
|
||||
exchangeAPI.init = function refreshDataFromBlockchain() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let nodes, assets, tags, lastTx;
|
||||
|
||||
@ -88,6 +88,11 @@ module.exports = function App(secret) {
|
||||
app.post('/withdraw-token', Request.WithdrawToken);
|
||||
app.post('/get-transact', Request.GetUserTransacts);
|
||||
|
||||
//generate or discard sinks (admin only)
|
||||
app.post('/generate-sink', Request.GenerateSink);
|
||||
app.post('/reshare-sink', Request.DiscardSink);
|
||||
app.post('/discard-sink', Request.DiscardSink);
|
||||
|
||||
//convert from or to coin
|
||||
app.get('/get-convert-values', Request.GetConvertValues);
|
||||
app.post('/convert-to', Request.ConvertTo);
|
||||
|
||||
@ -218,11 +218,8 @@ function informLiveNodes(init) {
|
||||
} else if (!flag) {
|
||||
console.log("Starting the exchange...");
|
||||
//generate a sinkID for each group in starting list
|
||||
keys.sink_groups.generate_list.forEach(group => {
|
||||
let newSink = floCrypto.generateNewID();
|
||||
console.debug("Generated sink:", group, newSink.floID);
|
||||
sendSharesToNodes(newSink.floID, group, generateShares(newSink.privKey));
|
||||
})
|
||||
keys.sink_groups.initial_list.forEach(group =>
|
||||
generateSink(group).then(_ => null).catch(e => console.error(e)));
|
||||
}
|
||||
}).catch(error => console.error(error));
|
||||
});
|
||||
@ -276,6 +273,63 @@ function slaveConnect(floID, pubKey, ws, sinks) {
|
||||
}
|
||||
}
|
||||
|
||||
const eCode = require('../docs/scripts/floExchangeAPI').errorCode;
|
||||
|
||||
function generateSink(group) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!keys.sink_groups.generate_list.includes(group))
|
||||
return reject(INVALID(eCode.INVALID_VALUE, `Invalid Group ${group}`));
|
||||
try {
|
||||
let newSink = floCrypto.generateNewID();
|
||||
console.debug("Generated sink:", group, newSink.floID);
|
||||
sendSharesToNodes(newSink.floID, group, generateShares(newSink.privKey));
|
||||
resolve(`Generated ${newSink.floID} (${group})`);
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function reshareSink(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!floCrypto.validateAddr(data.id))
|
||||
return reject(INVALID(eCode.INVALID_VALUE, `Invalid ID ${id}`));
|
||||
else {
|
||||
let group = keys.sink_chest.find_group(id);
|
||||
if (!group)
|
||||
return reject(INVALID(eCode.NOT_FOUND, `ID ${id} not found`));
|
||||
else keys.checkIfDiscarded(id).then(result => {
|
||||
if (result)
|
||||
return reject(INVALID(eCode.NOT_FOUND, `ID is discarded`));
|
||||
try {
|
||||
reconstructShares(group, id);
|
||||
resolve(`Resharing ${id} (${group})`);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}).catch(error => reject(error))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function discardSink(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!floCrypto.validateAddr(data.id))
|
||||
return reject(INVALID(eCode.INVALID_VALUE, `Invalid ID ${id}`));
|
||||
else if (!keys.sink_chest.find_group(id))
|
||||
return reject(INVALID(eCode.NOT_FOUND, `ID ${id} not found`));
|
||||
else keys.checkIfDiscarded(id).then(result => {
|
||||
if (result)
|
||||
return reject(INVALID(eCode.DUPLICATE_ENTRY, `ID already discarded`));
|
||||
keys.discardSink(id).then(result => {
|
||||
console.debug("Discarded sink:", id);
|
||||
resolve(result);
|
||||
}).catch(error => reject(error))
|
||||
}).catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
function checkForDiscardedSinks() {
|
||||
let cur_time = Date.now(),
|
||||
all_sinks = keys.sink_chest.get_all();
|
||||
@ -401,6 +455,11 @@ function initProcess(app) {
|
||||
module.exports = {
|
||||
init: initProcess,
|
||||
collectAndCall,
|
||||
sink: {
|
||||
generate: generateSink,
|
||||
reshare: reshareSink,
|
||||
discard: discardSink
|
||||
},
|
||||
set nodeList(list) {
|
||||
nodeURL = list;
|
||||
nodeKBucket = new K_Bucket(floGlobals.adminID, Object.keys(nodeURL));
|
||||
|
||||
22
src/keys.js
22
src/keys.js
@ -289,14 +289,25 @@ function checkIfDiscarded(id) {
|
||||
})
|
||||
}
|
||||
|
||||
function discardSink(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("INSERT INTO discardedSinks(floID) VALUE (?)", [id])
|
||||
.then(result => resolve(`Discarded ${id}`))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
//Sink groups and chest
|
||||
const sink_groups = {
|
||||
get EXCHANGE() { return "exchange" },
|
||||
get CONVERT() { return "convert" },
|
||||
get BLOCKCHAIN_BONDS() { return "blockchain_bonds" },
|
||||
get BOBS_FUND() { return "bobs_fund" },
|
||||
get generate_list() { //list to generate when starting exchange
|
||||
get initial_list() { //list to generate when starting exchange
|
||||
return [this.EXCHANGE, this.CONVERT]
|
||||
},
|
||||
get generate_list() { //list allowed to generate
|
||||
return [this.EXCHANGE, this.CONVERT, this.BLOCKCHAIN_BONDS, this.BOBS_FUND]
|
||||
}
|
||||
};
|
||||
|
||||
@ -343,6 +354,14 @@ const sink_ids = {}, sink_chest = {
|
||||
i = floCrypto.randInt(0, ids.length);
|
||||
return ids[i];
|
||||
},
|
||||
find_group(id) {
|
||||
let group = null;
|
||||
for (let g in sink_ids)
|
||||
if (id in sink_ids[g]) {
|
||||
group = g; break;
|
||||
}
|
||||
return group;
|
||||
},
|
||||
get_all() {
|
||||
let ids = {};
|
||||
for (let g in sink_ids)
|
||||
@ -359,6 +378,7 @@ module.exports = {
|
||||
getStoredList,
|
||||
getDiscardedList,
|
||||
checkIfDiscarded,
|
||||
discardSink,
|
||||
set node_priv(key) {
|
||||
_.node_priv = key;
|
||||
},
|
||||
|
||||
@ -6,6 +6,7 @@ const conversion = require('./services/conversion');
|
||||
const blockchain_bonds = require("./services/bonds");
|
||||
const bobs_fund = require("./services/bobs-fund");
|
||||
const background = require("./background");
|
||||
const sink = require("./backup/head").sink;
|
||||
const keys = require("./keys");
|
||||
|
||||
const {
|
||||
@ -307,6 +308,47 @@ function RemoveDistributor(req, res) {
|
||||
}, () => market.removeDistributor(data.distributor, data.asset));
|
||||
}
|
||||
|
||||
function GenerateSink(req, res) {
|
||||
let data = req.body;
|
||||
if (data.floID !== floGlobals.adminID)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied"));
|
||||
else if (!data.pubKey)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Public key missing"));
|
||||
else processRequest(res, data.floID, data.pubKey, data.sign, "Generate Sink", {
|
||||
type: "generate_sink",
|
||||
group: data.group,
|
||||
timestamp: data.timestamp
|
||||
}, () => sink.generate(group));
|
||||
}
|
||||
|
||||
function ReshareSink(req, res) {
|
||||
let data = req.body;
|
||||
if (data.floID !== floGlobals.adminID)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied"));
|
||||
else if (!data.pubKey)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Public key missing"));
|
||||
else if (!floCrypto.validateAddr(data.id))
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_VALUE, `Invalid ID ${data.id}`));
|
||||
else processRequest(res, data.floID, data.pubKey, data.sign, "Reshare Sink", {
|
||||
type: "reshare_sink",
|
||||
id: data.id,
|
||||
timestamp: data.timestamp
|
||||
}, () => sink.reshare(id));
|
||||
}
|
||||
|
||||
function DiscardSink(req, res) {
|
||||
let data = req.body;
|
||||
if (data.floID !== floGlobals.adminID)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.ACCESS_DENIED, "Access Denied"));
|
||||
else if (!data.pubKey)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Public key missing"));
|
||||
else processRequest(res, data.floID, data.pubKey, data.sign, "Discard Sink", {
|
||||
type: "discard_sink",
|
||||
id: data.id,
|
||||
timestamp: data.timestamp
|
||||
}, () => sink.discard(id));
|
||||
}
|
||||
|
||||
function ConvertTo(req, res) {
|
||||
let data = req.body;
|
||||
processRequest(res, data.floID, data.pubKey, data.sign, "Conversion", {
|
||||
@ -518,7 +560,7 @@ function GetSink(req, res) {
|
||||
if (!service)
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Missing service parameter"));
|
||||
else if (!(service in serviceList))
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_TYPE, "Invalid service parameter"));
|
||||
res.status(INVALID.e_code).send(INVALID.str(eCode.INVALID_VALUE, "Invalid service parameter"));
|
||||
else {
|
||||
let group;
|
||||
switch (service) {
|
||||
@ -640,6 +682,9 @@ module.exports = {
|
||||
RemoveUserTag,
|
||||
AddDistributor,
|
||||
RemoveDistributor,
|
||||
GenerateSink,
|
||||
ReshareSink,
|
||||
DiscardSink,
|
||||
GetConvertValues,
|
||||
ConvertTo,
|
||||
ConvertFrom,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user