Skip to content
Snippets Groups Projects
Commit 868061ba authored by Hernán Hegykozi's avatar Hernán Hegykozi
Browse files

Commit Inicial

parents
No related branches found
No related tags found
No related merge requests found
node_modules
npm-debug.log
Dockerfile
.dockerignore
\ No newline at end of file
node_modules
FROM node:16
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
EXPOSE 3030
CMD [ "node", "server.js" ]
\ No newline at end of file
# Introduction
TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.
# Getting Started
TODO: Guide users through getting your code up and running on their own system. In this section you can talk about:
1. Installation process
2. Software dependencies
3. Latest releases
4. API references
# Build and Test
TODO: Describe and show how to build your code and run the tests.
# Contribute
TODO: Explain how other users and developers can contribute to make your code better.
If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files:
- [ASP.NET Core](https://github.com/aspnet/Home)
- [Visual Studio Code](https://github.com/Microsoft/vscode)
- [Chakra Core](https://github.com/Microsoft/ChakraCore)
\ No newline at end of file
const bodyParser = require('body-parser');
const Web3 = require('web3');
const Tx = require('ethereumjs-tx');
const base64 = require('nodejs-base64-encode');
const sha256 = require('js-sha256');
const utils = require('./utils.js');
const config = require('./config.js');
const web3 = new Web3(new Web3.providers.HttpProvider(config.server.url))
const contract = new web3.eth.Contract(config.contract.ABI, config.contract.address);
module.exports = {
stamp : async function (req, res){
const now = new Date();
try{
const file_hash = req.body.file_hash;
var ots;
const timeStamp = now.getTime();
console.log("[" + utils.dateFormat(now, "%d/%m/%Y %H:%M:%S", false) + "] : Stamp (" + file_hash + ")");
var hash = sha256.create();
hash.update(file_hash.toString() + config.account.address.toString() + config.contract.address.toString() + timeStamp.toString());
ots = hash.hex() + config.contract.CURRENT_CONTRACT_VERSION;
const txCount = await web3.eth.getTransactionCount(config.account.address);
const data = contract.methods.stamp(ots, file_hash).encodeABI();
// Construir la transaccion
const txObject = {
nonce: web3.utils.toHex(txCount),
chainId: 200941592,
to: config.contract.address,
gas: 250000,
// TODO: revisar que el precio sea automático
gasPrice: 1000000000,
data: data
}
// Firmar la transaccion
const tx = new Tx(txObject);
tx.sign(config.account.privateKey);
const serializeTransaction = tx.serialize();
const raw = '0x' + serializeTransaction.toString('hex');
// Transmitir la transacción
const tx_sended = await web3.eth.sendSignedTransaction(raw);
const tx_hash = tx_sended.transactionHash;
comprobante_ots = '0x-' + ots + '-' + tx_hash;
// Si está todo bien, retorno el OpenTimeStamp definitivo para luego comprobar si el hash del archivo junto con este comprobante son válidos
comprobante_ots = base64.encode(comprobante_ots.toString(), 'base64');
return res.json({
temporary_rd: comprobante_ots,
status: "success"
});
}
catch(err){
console.log("[" + utils.dateFormat(now, "%d/%m/%Y %H:%M:%S", false) + "] : ERROR Stamp : ", err);
return res.status(500).json({
messages: "No se pudo realizar la operacion",
status: "failure"
});
};
},
verify : async function (req, res){
const now = new Date();
try{
const file_hash = req.body.file_hash;
const base64_ots = req.body.rd;
console.log("[" + utils.dateFormat(now, "%d/%m/%Y %H:%M:%S", false) + "] : Verify (" + file_hash + ", "+ base64_ots + ")");
// Transformo datos
const aux_ots = base64.decode(base64_ots.toString(), 'base64');
var array_ots = aux_ots.split('-');
// OTS definitivo
var permanent_ots;
const ispermanent = array_ots[0] == '1x'? true : false;
var ots = "";
var tx_hash = "";
//Si el ots enviado a verificar es el permanente o el temporal
if(ispermanent)
{
ots = array_ots[2];
tx_hash = array_ots[3];
}
else{
ots = array_ots[1];
tx_hash = array_ots[2];
}
var tx = await web3.eth.getTransaction(tx_hash);
// Significa que la TX aún no se incluye en un bloque.
if(!tx.blockNumber){
return res.json({
messages: "La transacción se encuentra pendiente de subida a la Blockchain",
status: "pending"
});
}
// Verifico si el OTS + File_Hash enviado son válidos
const result_verify = await contract.methods.verify(ots,file_hash).call({from: config.account.address});
if(result_verify){
const block_number = await contract.methods.getBlockNumber(ots).call();
// Tengo que obtener el bloque entero, para sacar su timestamp
const block = await web3.eth.getBlock(block_number);
var permanent_ots = "1x" + '-' + file_hash + '-' + ots + '-' + tx_hash + '-' + block_number
permanent_ots = base64.encode(permanent_ots.toString(), 'base64');
var d = new Date(block.timestamp * 1000);
var date_block = utils.dateFormat(d, "%d/%m/%Y %H:%M:%S", false);
return res.json({
permanent_rd: permanent_ots,
messages: "El archivo "+file_hash+" fue ingresado en el bloque "+block_number+" el "+ date_block,
status: "success",
attestation_time: date_block,
});
} else {
return res.status(404).json({
messages: "No se encontró el archivo",
status: "failure"
});
}
}
catch(err){
console.log("[" + utils.dateFormat(now, "%d/%m/%Y %H:%M:%S", false) + "] : ERROR Verify : ", err);
return res.status(500).json({
messages: "No se pudo realizar la operacion",
status: "failure"
});
}
}
}
var account = {
address : process.env.ACCOUNTADDRESS,
privateKey : Buffer.from(
process.env.ACCOUNTPRIVATEKEY,
'hex',
),
}
var contract = {
CURRENT_CONTRACT_VERSION : "01",
address : "0x7cbf323520d6fda0858b85dc357db6143fbe997b",
ABI : [{"constant":true,"inputs":[{"name":"ots","type":"string"}],"name":"getHash","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"ots","type":"string"}],"name":"getBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"ots","type":"string"},{"name":"file_hash","type":"string"}],"name":"verify","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"selfDestroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ots","type":"string"},{"name":"file_hash","type":"string"}],"name":"stamp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"accountAddress"},{"indexed":true,"name":"hash","type":"string"},{"indexed":true,"name":"ots","type":"string"}],"name":"Stamped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"accountAddress"}],"name":"Deploy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"accountAddress"}],"name":"SelfDestroy","type":"event"}]
}
var server = {
url:process.env.SERVER
}
exports.account = account;
exports.contract = contract;
exports.server = server;
\ No newline at end of file
const { Router } = require('express');
const router = Router();
const config = require('./config.js');
const BfaController = require('./bfacontroller.js');
router.get('/status', (req, res) => {
res.send('ok');
})
router.get('/address', (req, res) => {
res.send(config.account.address);
})
router.post('/stamp', async (req, res) => {
await BfaController.stamp(req, res);
})
router.post('/verify', async (req, res) => {
await BfaController.verify(req, res);
})
module.exports = router;
\ No newline at end of file
var dateFormat = function (date, fstr, utc) {
utc = utc ? 'getUTC' : 'get';
return fstr.replace (/%[YmdHMS]/g, function (m) {
switch (m) {
case '%Y': return date[utc + 'FullYear'] (); // no leading zeros required
case '%m': m = 1 + date[utc + 'Month'] (); break;
case '%d': m = date[utc + 'Date'] (); break;
case '%H': m = date[utc + 'Hours'] (); break;
case '%M': m = date[utc + 'Minutes'] (); break;
case '%S': m = date[utc + 'Seconds'] (); break;
default: return m.slice (1); // unknown code, remove %
}
// add leading zero if required
return ('0' + m).slice (-2);
});
}
var promisify = (inner) =>
new Promise((resolve, reject) =>
inner((err, res) => {
if (err) { reject(err) }
resolve(res);
})
);
exports.dateFormat = dateFormat;
exports.promisify = promisify;
\ No newline at end of file
This diff is collapsed.
{
"name": "apitsa1",
"version": "1.0.0",
"description": "Api TSA de BlockChain Federal Argentina",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"author": "Hernan Hegykozi",
"license": "MIT",
"dependencies": {
"body-parser": "^1.19.2",
"dateformat": "^5.0.3",
"ethereumjs-tx": "^1.3.7",
"express": "^4.17.3",
"js-sha256": "^0.9.0",
"nodejs-base64-encode": "^1.1.0",
"web3": "^1.7.1"
}
}
const bodyParser = require('body-parser')
const express = require("express")
const app = express()
const port = process.env.PORT || 3030;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(require('./api/routes'));
app.listen(port, () => console.log("Start Server (Port " + port + ")....OK"));
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment