Skip to content

Instantly share code, notes, and snippets.

@nnkken
Last active June 22, 2018 08:03
Show Gist options
  • Select an option

  • Save nnkken/6a08bab720d1ac8a6046ac4749b3ef54 to your computer and use it in GitHub Desktop.

Select an option

Save nnkken/6a08bab720d1ac8a6046ac4749b3ef54 to your computer and use it in GitHub Desktop.
module.exports = {
storageProviders: {
puttyimages: '0x0102030405060708091011121314151617181920',
},
};
const express = require('express');
const bodyParser = require('body-parser');
const ipfsAPI = require('ipfs-api');
const level = require('level');
const sigUtil = require('eth-sig-util');
const jsonStringify = require('json-stable-stringify');
const { promisify } = require('util');
const ipfs = ipfsAPI({ host: 'localhost', port: '5001', protocol: 'http' });
const ipfsDagPut = promisify(ipfs.dag.put);
const db = level('./likechain');
const dbGet = promisify((...args) => db.get(...args));
const dbPut = promisify((...args) => db.put(...args));
const app = express();
const { storageProviders } = require('./config.js');
function checkBase58(s) {
return /^[a-km-zA-HJ-NP-Z1-9+/]+$/.test(s);
}
function checkHex(s) {
return /^[a-fA-F0-9]+$/.test(s);
}
function verifyMetadata(metadata) {
if (!Array.isArray(metadata.creator)) return false;
if (metadata.creator.length < 1) return false;
if (metadata.dateCreated === undefined) return false;
if (metadata.description === undefined) return false;
if (metadata.license === undefined) return false;
if (!checkHex(metadata.likeFingerprint)) return false;
if (!Array.isArray(metadata.likeFootprint)) return false;
if (metadata.likePreviousVersion === undefined) return false;
if (metadata.type === undefined) return false;
if (metadata.uploadDate === undefined) return false;
return true;
}
app.post('/upload', bodyParser.json(), async (req, res) => {
try {
const {
likeIpfs,
metadata,
ownerSig,
storageProvider,
storageProviderSig,
} = req.body;
if (
!likeIpfs || !metadata || !ownerSig || !storageProvider || !storageProviderSig
) {
throw new Error('Missing field(s)');
}
const { likeFingerprint, creator } = metadata;
if (!checkHex(likeFingerprint)) {
throw new Error('Invalid fingerprint');
}
if (!checkBase58(likeIpfs)) {
throw new Error('Invalid IPFS address');
}
const normalizedFingerprint = likeFingerprint.toLowerCase();
try {
await dbGet(normalizedFingerprint);
throw new Error('Content hash already occupied');
} catch (err) {
if (err.type !== 'NotFoundError') {
throw err;
}
// Not found, so OK to add
}
if (!verifyMetadata(metadata)) {
throw new Error('Invalid metadata');
}
const ownerSigString = jsonStringify(metadata);
console.log(ownerSigString);
const recoveredOwner = sigUtil.recoverPersonalSignature({
data: Buffer.from(ownerSigString).toString('hex'),
sig: ownerSig,
});
// TODO: query address of metadata.creator[0] (from like.co temporary)
console.log(creator[0]);
console.log(recoveredOwner);
const spAddr = storageProviders[storageProvider];
if (!spAddr) {
throw new Error('Invalid storage provider');
}
const spSigString = jsonStringify({ likeIpfs, metadata });
console.log(spSigString);
const recoveredSp = sigUtil.recoverPersonalSignature({
data: Buffer.from(spSigString).toString(),
sig: storageProviderSig,
});
if (spAddr.toLowerCase() !== recoveredSp.toLowerCase()) {
throw new Error('Invalid storage provider signature');
}
const cid = await ipfsDagPut(metadata, { format: 'dag-cbor', hashAlg: 'sha2-256' });
const metadataIpldAddr = cid.toBaseEncodedString();
await ipfs.pin.add(metadataIpldAddr);
await dbPut(normalizedFingerprint, metadataIpldAddr);
res.send({ status: 'success', metadataIpldAddr });
res.end();
} catch (err) {
console.error(err);
res.status(400);
res.send(err.message || err);
}
});
app.get('/content/:fingerprint', async (req, res) => {
try {
const { fingerprint } = req.params;
if (!checkHex(fingerprint)) {
throw new Error('Invalid fingerprint');
}
const normalizedFingerprint = fingerprint.toLowerCase();
const metadataIpldAddr = await dbGet(normalizedFingerprint);
res.send({ status: 'success', metadataIpldAddr });
} catch (err) {
console.error(err);
res.status(400);
res.send(err.message || err);
}
});
app.listen(8000);
{
"name": "fake-likechain",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.18.3",
"eth-sig-util": "^1.4.2",
"express": "^4.16.3",
"ipfs-api": "^22.0.1",
"json-stable-stringify": "^1.0.1",
"level": "^4.0.0",
"web3-utils": "^1.0.0-beta.34"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment