Skip to content

Commit

Permalink
ipfs connection to local or embedded node (#86)
Browse files Browse the repository at this point in the history
* handle ipfs connection in view
fallback to embedded if local doesn't work
add buffer webpack plugin

* fallback to fetching from gateways
add verification of ipfs content
can input local node address
remove ipfs-core and ipfs-provider

Co-authored-by: stobiewan <[email protected]>
  • Loading branch information
stobiewan and stobiewan authored Apr 19, 2022
1 parent 013ddc0 commit 78bb61b
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 41 deletions.
20 changes: 13 additions & 7 deletions dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,26 @@
#result {
white-space: pre;
}

#localNode {
width: 210px;
}
</style>
</head>
<body>
<h1>dmap</h1>

<label for="dpath">dmap://</label>
<input type="text" id="dpath" name="dpath" value="free.weth">
<input type="button" id="btnGet" value="Get">
<div>
<label for="localNode">ipfs node</label>
<input type="text" id="localNode" name="localNode" value="/ip4/127.0.0.1/tcp/5001" title="optional">
</div>

<div id="result"></div>
<div>
<label for="dpath">dmap://</label>
<input type="text" id="dpath" name="dpath" value="free.weth">
<input type="button" id="btnGet" value="Get">
</div>

<!--<script defer src="dependencies.js" crossorigin="no-cors"></script>-->
<!--<script defer src="main.js"></script>-->
<div id="result"></div>

<script defer src="dependencies.js"></script>
<script defer src="main.js"></script>
Expand Down
25 changes: 5 additions & 20 deletions dmap.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
const ebnf = require('ebnf')
const multiformats = require('multiformats')

const ethers = require('ethers')
const { b32 } = require('minihat');

const multiformats = require('multiformats')
const abi = require('./artifacts/core/dmap.sol/Dmap.json').abi
const dmap_i = new ethers.utils.Interface(abi)

Expand Down Expand Up @@ -91,11 +88,11 @@ lib.walk = async (dmap, path) => {
if (zone === '0x' + '00'.repeat(20)) {
fail(`zero register`)
}
const fullname = '0x' + lib._strToHex(step.name) + '00'.repeat(32-step.name.length);
const fullname = '0x' + Buffer.from(step.name).toString('hex') + '00'.repeat(32-step.name.length);
[meta, data] = await lib.get(dmap, zone, fullname)
if (step.locked) {
need(ctx.locked, `Encountered ':' in unlocked subpath`)
need((lib._hexToArrayBuffer(meta)[0] & lib.FLAG_LOCK) !== 0, `Entry is not locked`)
need((Buffer.from(meta.slice(2), 'hex')[0] & lib.FLAG_LOCK) !== 0, `Entry is not locked`)
ctx.locked = true
}
ctx.locked = step.locked
Expand All @@ -118,8 +115,8 @@ lib.prepareCID = (cidStr, lock) => {
}

lib.unpackCID = (metaStr, dataStr) => {
const meta = lib._hexToArrayBuffer(metaStr)
const data = lib._hexToArrayBuffer(dataStr)
const meta = Buffer.from(metaStr.slice(2), 'hex')
const data = Buffer.from(dataStr.slice(2), 'hex')
const prefixLen = meta[prefLenIndex]
const specs = multiformats.CID.inspectBytes(meta.slice(-prefixLen))
const hashLen = specs.digestSize
Expand All @@ -135,15 +132,3 @@ lib.readCID = async (dmap, path) => {
const packed = await lib.walk(dmap, path)
return lib.unpackCID(packed.meta, packed.data)
}

lib._hexToArrayBuffer = hex => {
const bytes = []
for (let c = 2; c < hex.length; c += 2)
bytes.push(parseInt(hex.slice(c, c + 2), 16))
return new Uint8Array(bytes)
}

lib._strToHex = str => {
let codes = str.split('').map(c => c.charCodeAt(0))
return codes.map(c => c.toString(16)).join('')
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"@nomiclabs/hardhat-ethers": "^2.0.5",
"@types/mocha": "^9.0.0",
"hardhat": "^2.8.3",
"ipfs-http-client": "^56.0.2",
"minihat": "^0.0.5",
"v8": "^0.1.0",
"web3-utils": "^1.7.1",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2"
Expand Down
63 changes: 50 additions & 13 deletions view/app.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
import { ethers } from 'ethers'
const dpack = require('@etherpacks/dpack')
import { CID } from 'multiformats/cid'
import { sha256 } from 'multiformats/hashes/sha2'
const dmap = require('../dmap.js')
const dmapAddress = '0x7fA88e1014B0640833a03ACfEC71F242b5fBDC85'
const dmapArtifact = require('../artifacts/core/dmap.sol/Dmap.json')
const IPFS = require('ipfs-http-client')

window.onload =()=> {
const $ = document.querySelector.bind(document);
const result = $('#result')
const gateways = ['https://ipfs.fleek.co/ipfs/',
'https://gateway.pinata.cloud/ipfs/',
'https://cloudflare-ipfs.com/ipfs/',
'https://storry.tv/ipfs/',
'https://ipfs.io/ipfs/',
'https://hub.textile.io/ipfs/']

const resolveCID = async (cid, targetDigest, nodeAddress) => {
const verify = async bytes => {
const hash = await sha256.digest(bytes)
const resultDigest = JSON.stringify(hash.digest)
return targetDigest === resultDigest
}
const node = IPFS.create(nodeAddress)
const catResponse = await node.cat(cid)
// initially handle only single chunk verification and sha256
try {
const chunk = await catResponse.next()
if(await verify(chunk.value)) {
return chunk.value
}
} catch(e) {}

for (const gateway of gateways) {
const url = gateway + cid
try {
const response = await fetch(url);
const reader = response.body.getReader();
let readRes = await reader.read();
if (await verify(readRes.value)) {
return readRes.value
}
} catch (e) {}
}
throw 'unable to resolve cid'
}

window.onload = async() => {
const $ = document.querySelector.bind(document);
const line =s=> { $('#result').textContent += s + '\n' }

$('#btnGet').addEventListener('click', async () => {
Expand All @@ -32,18 +69,18 @@ window.onload =()=> {
}

try {
// display json content from a CID if we can
const cidResult = dmap.unpackCID(walkResult.meta, walkResult.data)
line(`ipfs: ${cidResult}`)
const ipfsResult = await dpack.getIpfsJson(cidResult)
line(JSON.stringify(ipfsResult, null, 4))
// display ipfs content from a CID if we can, otherwise display as text
const cid = dmap.unpackCID(walkResult.meta, walkResult.data)
line(`ipfs: ${cid}`)
const targetDigest = JSON.stringify(CID.parse(cid).multihash.digest)
const resolved = await resolveCID(cid, targetDigest, $('#localNode').value)
let utf8decoder = new TextDecoder()
line(utf8decoder.decode(resolved))
}
catch(e){
// otherwise show text
let utf8decoder = new TextDecoder()
const bytes = dmap._hexToArrayBuffer(walkResult.data)
let i
for (i = 0; i < bytes.length; i++) {
const bytes = Buffer.from(walkResult.data.slice(2), 'hex')
for (var i = 0; i < bytes.length; i++) {
if (bytes[bytes.length -1 - i] !== 0) {
break
}
Expand Down
6 changes: 6 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const path = require('path');
const webpack = require('webpack');

module.exports = {
mode: 'production',
Expand All @@ -9,6 +10,11 @@ module.exports = {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
})
],
optimization: {
minimize: false,
splitChunks: {
Expand Down

0 comments on commit 78bb61b

Please sign in to comment.