星鉴网>技术干货>使用Stellar和IPFS构建应用程序

使用Stellar和IPFS构建应用程序

2018/10/31 11:00:06 1299人阅读

【导读】 开始考虑使用Stellar区块链结合IPFS实际构建像HackerNews或Reddit这样分散版本论坛是什么样子。

  虽然以太坊一直是构建dApp的首选平台,但Stellar网络只需要极低的交易手续费,并且比其他区块链(包括以太坊)交易处理速度快得多。

  

  因此,我开始考虑使用Stellar区块链结合IPFS实际构建像HackerNews或Reddit这样分散版本论坛是什么样子。以下是我如何设想它的工作原理:

  

  

  让我们看看我们将如何实现这一目标。

  

  首先,我们需要在Stellar testnet上创建一个帐户 。什么是testnet?简单来说,它是一个区块链,是一个用于测试并且不需要支付任何实际费用的地方。在这种情况下,我们将使用10k假流明加载我们的测试帐户进行测试。

  

  下面,我们将构建一个小型JavsScript客户端,允许用户在应用程序上提交他们的帖子。我们可以直接在计划构建的应用程序上发现在这篇文章,方法是将其放入交易的备忘录字段中。

  

  不过事实上,Stellar网络只允许有限的备忘录格式 - 文本(最多28字节的UTF-8字符串),ID(无符号64位整数)或散列(十六进制格式的32字节散列)。因此,存储大量文本或JSON是不可能的。

  

  发送到IPFS

  

  这就是IPFS的用武之地 - P2P协议形式的网络,旨在链接所有计算机设备在分布式文件系统中存储和共享内容(将其视为git和BitTorrent结合后的产物)。

  

  下面,我们将获取该数据并将其存储在IPFS中的JSON对象中。

  

  import ipfsAPI from 'ipfs-api'  

  // I'm just using an IPFS gateway here for testing but in a real-world setting, we would run our own IPFS node so we can persist data 

  const ipfs = ipfsAPI({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' });

  const post = JSON.stringify({title: "'So exited!!!', content: 'This is my first post on the blockchain!', username: 'h4ck3r'})"

  const buffer = Buffer.from(post);

  ipfs.files.add(buffer, { pin: false }, (err, ipfsHash) => {

  console.log(ipfsHash[0].path) // => QmV3C3HFE8824KWYTMq5fbZyF93GTMz5W7h3uBG1oVZCv8

  });

  

  现在我们有一个足够哈希值来发送备忘录字段,虽然看起来可能还有一些问题。IPFS使用具有Base58编码的Multihash表示文件和对象的哈希值。前缀Qm对应于IPFS使用的算法(SHA-256)和长度(32字节)。

  

  所以看起来我们不能在我们的事务的Text字段中添加它,它只允许最多28个字节的字符串,也不能使用只允许32字节哈希的Hash字段。

  

  所以我们必须编写一个函数,将这个IPFS散列转换回十六进制格式的32字节散列:

  

  import bs58 from 'bs58' 

  this.getBytes32FromIpfsHash = (ipfsListing) => {

  // Decode the base58 string and then slice the first two bytes

  // which represent the function code and it's length, in this case:

  // function:0x12=sha2, size:0x20=256 bits

  return bs58.decode(ipfsListing).slice(2).toString('hex')

  }

  

  在区块链上添加它

  

  现在我们已经在备忘录字段中存储了正确的哈希,我们必须弄清楚如何发送此事务。一种选择是提示用户使用MetaPay ,它是Stellar的Chrome扩展钱包(有点像MetaMask for Stellar Lumens)。一旦安装了MetaPay,我们就可以设置如下的URL:

  

  <a ref='savePost' data-meta-pay

  href="https://stellar.meta.re/transaction?to=[address]&amount=1&memo=[txMemo]"

  target="_blank" >Save Post</a>

  

  现在,如果我们将它们放在一起,提交帖子逻辑将如下所示:

  

  import StellarSdk from 'stellar-sdk'

  // Add the post data to IPFS

  this.submitPost = (post) => {

  const buffer = Buffer.from(post);

  ipfs.files.add(buffer, (err, ipfsHash) => {

  this.txMemo = this.getBytes32FromIpfsHash(ipfsHash[0].path)

  this.refs['savePost'].click() // This will open the MetaPay popup

  this.confirmPayment(this.txMemo) // Listen to see if the transaction went through

  });

  } 

  // Check to see if the transaction went through

  this.confirmPayment = (ipfsHash) => {

  const server = new StellarSdk.Server('https://horizon-testnet.stellar.org');

  server.transactions().forAccount('OUR_ACCOUNT_ID').cursor('now').stream({

  onmessage: (transaction) => {

  if(transaction.memo == ipfsHash) {

  // Yes, it made it on the blockchain!

  transaction.operations().then((ops) => {

  var payment = ops._embedded.records[0];

  if(parseInt(parseFloat(payment.amount)) < 1) {

  console.error('Payment insufficient. Post not saved!');

  } else {

  this.pinIpfsListing(ipfsHash);

  }

  }).catch((error) => {

  error.target.close(); // Close stream

  console.error('Payment Error: ', error);

  alert('Error confirming payment. Try again later');

  });

  }

  },

  onerror: (error) => {

  error.target.close(); // Close stream

  console.error('Streaming Error: ', error);

  }

  });

  }

  

  这将打开所有包含预填充字段的MetaPay弹出窗口,我们将等待用户是否完成该事务,如果有,我们将进入下一步。

  

  

  存储到IPFS

  

  // If successful, pin our post on the IPFS node

  this.pinIpfsListing = (ipfsHash) => {

  ipfs.pin.add(ipfsHash)

  }

  

  请注意,当我们将数据添加到IPFS时,我们没有固定它。如果不固定帖子,我们的数据将不会永久存储在IPFS节点上,最终将被垃圾收集。

  

  因此,在某种程度上,小额交易费用可以帮助我们支付固定数据/运行IPFS节点的成本,并确保数据可供所有用户使用。

  

  从区块链中读取并在IPFS上找到它

  

  现在,当其他用户访问该应用程序时,我们会将所有发布的事务提取到此应用程序的帐户,获取备忘录字段,将其编码转为Base58并从IPFS中提取数据:

  

  import StellarSdk from 'stellar-sdk'

  import ipfsAPI from 'ipfs-api'

  this.getIpfsHashFromBytes32 = (bytes32Hex) => {

  // Add our default ipfs values for first 2 bytes:

  // function:0x12=sha2, size:0x20=256 bits

  const hashHex = "1220" + bytes32Hex

  const hashBytes = Buffer.from(hashHex, 'hex');

  const hashStr = bs58.encode(hashBytes)

  return hashStr

  }

  const server = new StellarSdk.Server('https://horizon-testnet.stellar.org');

  const ipfs = ipfsAPI({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' });

  let posts = [];

  server.transactions()

  .forAccount('OUR_ACCOUNT_ID')

  .order('desc')

  .call()

  .then((page) => {

  page.records.forEach(record => {

  if (record.memo) {

  const ipfsListing = this.getIpfsHashFromBytes32(record.memo)

  ipfs.files.get(ipfsListing, function (err, files) {

  files.forEach((file) => {

  const post = file.content.toString('utf8')

  posts.push(post) // Show this to the user

  })

  })

  }

  });

  });

 

  分权

  

  这种架构确保我们的数据是分散的,但应用本身呢?如果应用程序出现故障,用户可以编写另一个可以从该帐户的区块链中读取的客户端,并从IPFS中提取相应的数据。

  

  其实,我们可以更进一步,通过利用manageData帐户操作将客户端代码存储在区块链上。

  

  这样的东西可以是应用程序的构建/部署链的一部分,因此每次发布新版本时,它也会添加到区块链中:

  

  import fs from 'fs'

  this.publishClient = () {

  const code = fs.readFileSync('my_project/client.js');

  ipfs.files.add(buffer, (err, ipfsHash) => {

  const server = new StellarSdk.Server('https://horizon-testnet.stellar.org');

  server.loadAccount('OUR_ACCOUNT_ID').then((base) => {

  const tx = new StellarSdk.TransactionBuilder(base);

  const data = {name: 'v1.0.0', value: ipfsHash[0].path};

  tx.addOperation(StellarSdk.Operation.manageData(data));

  var builtTx = tx.build();

  builtTx.sign(StellarSdk.Keypair.fromSecret('OUR_ACCOUNT_SECRET'));

  return server.submitTransaction(builtTx);

  });

  });

  }

  

  虽然要记住一些事项,但每个DataEntry都会增加帐户所需的维护费用。因此,我们可能只希望在帐户上维护客户端代码库的最新版本或最后几个版本。但这足以使我们的演示应用程序或多或少地分散。

  

  结论

  

  这是一个有趣的思想实验,但这个演示应用程序仍然没有管理评论、upvotes等功能,因为我们受到Stellar平台能力的限制。为了构建更先进的东西,我们需要在像以太坊或者NEO这样的真正的dApp平台上构建它,它具有实现这一目标的所有必要工具。IPFS与区块链技术可以完美组合,是构建分布式应用程序的绝佳选择。随着最近Facebook数据和用户隐私的争议,现在是时候考虑如何构建分散的社交应用程序了。在这个领域有很多有趣的工作,包括Datawallet ,Blockstack ,Akasha 等项目,这些项目在未来几年将会很有趣。

  

  本文翻译自https://dev.to/     作者:工程经理和全栈开发人员Jesal Gadhia

9

参与讨论

登录后参加评论......

全部评论 0

作者

返回顶部