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',
|
DUPLICATE_SIGNATURE: '017',
|
||||||
SESSION_INVALID: '018',
|
SESSION_INVALID: '018',
|
||||||
SESSION_EXPIRED: '019',
|
SESSION_EXPIRED: '019',
|
||||||
|
INVALID_VALUE: '020',
|
||||||
INVALID_TOKEN_NAME: '021',
|
INVALID_TOKEN_NAME: '021',
|
||||||
INVALID_NUMBER: '022',
|
INVALID_NUMBER: '022',
|
||||||
INVALID_TYPE: '023',
|
INVALID_TYPE: '023',
|
||||||
@ -610,7 +611,7 @@
|
|||||||
exchangeAPI.getSink = function (service = serviceList.EXCHANGE) {
|
exchangeAPI.getSink = function (service = serviceList.EXCHANGE) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!(service in serviceList))
|
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)
|
fetch_api('/get-sink?service=' + service)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
responseParse(result, false)
|
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() {
|
exchangeAPI.init = function refreshDataFromBlockchain() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let nodes, assets, tags, lastTx;
|
let nodes, assets, tags, lastTx;
|
||||||
|
|||||||
@ -88,6 +88,11 @@ module.exports = function App(secret) {
|
|||||||
app.post('/withdraw-token', Request.WithdrawToken);
|
app.post('/withdraw-token', Request.WithdrawToken);
|
||||||
app.post('/get-transact', Request.GetUserTransacts);
|
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
|
//convert from or to coin
|
||||||
app.get('/get-convert-values', Request.GetConvertValues);
|
app.get('/get-convert-values', Request.GetConvertValues);
|
||||||
app.post('/convert-to', Request.ConvertTo);
|
app.post('/convert-to', Request.ConvertTo);
|
||||||
|
|||||||
@ -218,11 +218,8 @@ function informLiveNodes(init) {
|
|||||||
} else if (!flag) {
|
} else if (!flag) {
|
||||||
console.log("Starting the exchange...");
|
console.log("Starting the exchange...");
|
||||||
//generate a sinkID for each group in starting list
|
//generate a sinkID for each group in starting list
|
||||||
keys.sink_groups.generate_list.forEach(group => {
|
keys.sink_groups.initial_list.forEach(group =>
|
||||||
let newSink = floCrypto.generateNewID();
|
generateSink(group).then(_ => null).catch(e => console.error(e)));
|
||||||
console.debug("Generated sink:", group, newSink.floID);
|
|
||||||
sendSharesToNodes(newSink.floID, group, generateShares(newSink.privKey));
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}).catch(error => console.error(error));
|
}).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() {
|
function checkForDiscardedSinks() {
|
||||||
let cur_time = Date.now(),
|
let cur_time = Date.now(),
|
||||||
all_sinks = keys.sink_chest.get_all();
|
all_sinks = keys.sink_chest.get_all();
|
||||||
@ -401,6 +455,11 @@ function initProcess(app) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
init: initProcess,
|
init: initProcess,
|
||||||
collectAndCall,
|
collectAndCall,
|
||||||
|
sink: {
|
||||||
|
generate: generateSink,
|
||||||
|
reshare: reshareSink,
|
||||||
|
discard: discardSink
|
||||||
|
},
|
||||||
set nodeList(list) {
|
set nodeList(list) {
|
||||||
nodeURL = list;
|
nodeURL = list;
|
||||||
nodeKBucket = new K_Bucket(floGlobals.adminID, Object.keys(nodeURL));
|
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
|
//Sink groups and chest
|
||||||
const sink_groups = {
|
const sink_groups = {
|
||||||
get EXCHANGE() { return "exchange" },
|
get EXCHANGE() { return "exchange" },
|
||||||
get CONVERT() { return "convert" },
|
get CONVERT() { return "convert" },
|
||||||
get BLOCKCHAIN_BONDS() { return "blockchain_bonds" },
|
get BLOCKCHAIN_BONDS() { return "blockchain_bonds" },
|
||||||
get BOBS_FUND() { return "bobs_fund" },
|
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]
|
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);
|
i = floCrypto.randInt(0, ids.length);
|
||||||
return ids[i];
|
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() {
|
get_all() {
|
||||||
let ids = {};
|
let ids = {};
|
||||||
for (let g in sink_ids)
|
for (let g in sink_ids)
|
||||||
@ -359,6 +378,7 @@ module.exports = {
|
|||||||
getStoredList,
|
getStoredList,
|
||||||
getDiscardedList,
|
getDiscardedList,
|
||||||
checkIfDiscarded,
|
checkIfDiscarded,
|
||||||
|
discardSink,
|
||||||
set node_priv(key) {
|
set node_priv(key) {
|
||||||
_.node_priv = key;
|
_.node_priv = key;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,6 +6,7 @@ const conversion = require('./services/conversion');
|
|||||||
const blockchain_bonds = require("./services/bonds");
|
const blockchain_bonds = require("./services/bonds");
|
||||||
const bobs_fund = require("./services/bobs-fund");
|
const bobs_fund = require("./services/bobs-fund");
|
||||||
const background = require("./background");
|
const background = require("./background");
|
||||||
|
const sink = require("./backup/head").sink;
|
||||||
const keys = require("./keys");
|
const keys = require("./keys");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -307,6 +308,47 @@ function RemoveDistributor(req, res) {
|
|||||||
}, () => market.removeDistributor(data.distributor, data.asset));
|
}, () => 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) {
|
function ConvertTo(req, res) {
|
||||||
let data = req.body;
|
let data = req.body;
|
||||||
processRequest(res, data.floID, data.pubKey, data.sign, "Conversion", {
|
processRequest(res, data.floID, data.pubKey, data.sign, "Conversion", {
|
||||||
@ -518,7 +560,7 @@ function GetSink(req, res) {
|
|||||||
if (!service)
|
if (!service)
|
||||||
res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Missing service parameter"));
|
res.status(INVALID.e_code).send(INVALID.str(eCode.MISSING_PARAMETER, "Missing service parameter"));
|
||||||
else if (!(service in serviceList))
|
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 {
|
else {
|
||||||
let group;
|
let group;
|
||||||
switch (service) {
|
switch (service) {
|
||||||
@ -640,6 +682,9 @@ module.exports = {
|
|||||||
RemoveUserTag,
|
RemoveUserTag,
|
||||||
AddDistributor,
|
AddDistributor,
|
||||||
RemoveDistributor,
|
RemoveDistributor,
|
||||||
|
GenerateSink,
|
||||||
|
ReshareSink,
|
||||||
|
DiscardSink,
|
||||||
GetConvertValues,
|
GetConvertValues,
|
||||||
ConvertTo,
|
ConvertTo,
|
||||||
ConvertFrom,
|
ConvertFrom,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user