您好,登录后才能下订单哦!
本篇内容介绍了“如何将JSON文件存储在IPFS上”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
如何将JSON文件存储在IPFS上,并使用Oraclize访问智能合约中的数据呢?
以太坊是一个成熟的区块链,使开发人员能够创建智能合约,在区块链上执行的程序可以由交易触发。人们经常将区块链称为数据库,但使用区块链作为数据存储非常昂贵。
以目前的价格(530美元,4gwei)在以太坊上存储250GB将花费你106,000,000美元。一般来说,我们可以忍受高成本因为我们:
不会在以太坊区块链上保存那么多数据。
区块链的审查制度,透明度和稳健性是值得的。
如果你是以太坊的新手,请查看此 介绍 。
IPFS(星际文件系统)对区块链存储有一些保证,即去中心化和防篡改,但不比传统的磁盘空间花费更多费用。使用EBS 250GB存储运行EC2 t2.micro实例将花费你大约15美元/月。IPFS的一个独特功能是它处理文件的方式。它不使用基于位置的寻址(如域名,IP地址,文件路径等),而是使用基于内容的寻址。将文件(或目录)添加到IPFS存储库后,可以通过其加密哈希来引用它。
$ ipfs add article.json added Qmd4PvCKbFbbB8krxajCSeHdLXQamdt7yFxFxzTbedwiYM article.json $ ipfs cat Qmd4PvCKbFbbB8krxajCSeHdLXQamdt7yFxFxzTbedwiYM { "title": "This is an awesome title", "content": "paragraph2\r\n\r\nparagraph3"} $ curl https://ipfs.io/ipfs/Qmd4PvCKbFbbB8krxajCSeHdLXQamdt7yFxFxzTbedwiYM{ "title": "This is an awesome title", "content": "paragraph2\r\n\r\nparagraph3"}
然后,你可以使用IPFS客户端或任何公共网关访问文件。你还可以创建非公共网关,默认情况下使其成为可写(只读),并实现授权方案,以便以编程方式访问IPFS网络。
重要的是要了解IPFS不是一种服务,其他节点将存储你的内容。如果你的内容不受欢迎,如果他们没有固定哈希(他们不想租用磁盘空间),垃圾收集器会将其从其他节点中删除。只要网络上至少有一个对等体确实关心你的文件并且有兴趣存储它们,网络上的其他节点就可以轻松获取该文件。即使你的文件从网络中消失,也可以在以后再次添加,除非其内容发生更改,否则其地址(哈希)将相同。
尽管以太坊协议没有提供任何连接到IPFS的本地方式,但我们可以回到像Oraclize这样的离线解决方案来解决这个问题。Oraclize允许使用各种数据提供智能合约。其中一个可用的数据源是URL。我们可以使用公共网关从IPFS上的JSON文件中读取。依靠单个网关会很单薄。我们将要使用的另一个数据源是IPFS。通过使用JSON解析器(它是查询的一部分)读取Oraclize智能合约,我们可以在JSON文档中提取特定字段。
oraclize_query("IPFS", "json(Qmd4PvCKbFbbB8krxajCSeHdLXQamdt7yFxFxzTbedwiYM).title"));
如果Oraclize可以在20秒内获取文件,则可以预期获得异步请求。如果使用连接良好的节点上传文件,则不需要关注超时。我们的EC2(欧盟法兰克福)实例连接到大约750个同行。通过公共网关或本地运行守护进程获取文件几乎是即时的。响应是异步的,oraclize_query
调用返回查询id(bytes32)。你可以将其作为来自Oraclize的数据的标识符。
function __callback(bytes32 _queryId, string _data) public { require(msg.sender == oraclize_cbAddress()); process_data(_data); }
出于安全原因,我们希望确保只允许Oraclize调用__callback
函数。
你可以在GitHub上找到博客示例的完整代码库: tooploox/ipfs-eth-database
最初,我很担心性能表现。它是否可以像集中服务发送响应一样快速地获取IPFS上托管的JSON文件?结果令我很惊喜。
$ wrk -d10s https://ipfs.io/ipfs/Qmd4PvCKbFbbB8krxajCSeHdLXQamdt7yFxFxzTbedwiYM Running 10s test @ https://ipfs.io/ipfs/Qmd4PvCKbFbbB8krxajCSeHdLXQamdt7yFxFxzTbedwiYM 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 59.18ms 24.36ms 307.93ms 94.73% Req/Sec 86.34 15.48 101.00 85.57% 1695 requests in 10.05s, 1.38MB readRequests/sec: 168.72 Transfer/sec: 140.70KB
在我们审查博客时,作者必须在智能合约上调用addPost时仅输入IPFS哈希值。我们使用IPFS和Oraclize从文件中读取标题,以使用以太坊事件存储它。我们不需要为其他智能合约保留标题,因此使用事件对于我们的用例来说已经足够了。这可能不是最具开创性的例子,但很好地展示了如何优化低交易费用。
pragma solidity 0.4.24; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "./lib/usingOraclize.sol"; import "./lib/strings.sol"; contract Blog is usingOraclize, Ownable { using strings for *; mapping(address => string[]) public hashesByAuthor; mapping(bytes32 => string) public hashByQueryId; mapping(bytes32 => address) public authorByHash; event PostAdded(address indexed author, string hash, uint timestamp, string title); event PostSubmitted(address indexed author, string hash, bytes32 queryId); uint private gasLimit; constructor(uint _gasPrice, uint _gasLimit) public { setCustomOraclizeGasPrice(_gasPrice); setCustomOraclizeGasLimit(_gasLimit); } function getPrice(string _source) public view returns (uint) { return oraclize_getPrice(_source); } function setCustomOraclizeGasPrice(uint _gasPrice) public onlyOwner { oraclize_setCustomGasPrice(_gasPrice); } function setCustomOraclizeGasLimit(uint _gasLimit) public onlyOwner { gasLimit = _gasLimit; } function withdraw() public onlyOwner { owner.transfer(address(this).balance); } function __callback(bytes32 _queryId, string _title) public { require(msg.sender == oraclize_cbAddress()); require(bytes(hashByQueryId[_queryId]).length != 0); string memory hash = hashByQueryId[_queryId]; address author = authorByHash[keccak256(bytes(hash))]; hashesByAuthor[author].push(hash); emit PostAdded(author, hash, now, _title); } function addPost(string _hash) public payable returns (bool) { require(authorByHash[keccak256(bytes(_hash))] == address(0), "This post already exists"); require(msg.value >= oraclize_getPrice("IPFS"), "The fee is too low"); bytes32 queryId = oraclize_query("IPFS", "json(".toSlice().concat(_hash.toSlice()).toSlice().concat(").title".toSlice()), gasLimit); authorByHash[keccak256(bytes(_hash))] = msg.sender; hashByQueryId[queryId] = _hash; emit PostSubmitted(msg.sender, _hash, queryId); return true; } function getPriceOfAddingPost() public view returns (uint) { return oraclize_getPrice("IPFS"); } }
前端使用Web3读取事件,并为给定作者构建所有博客帖子的列表。
降价商品的内容也存储在IPFS上。它允许保留添加新博客帖子的固定费用。我们使用一系列公共IPFS,从我们自己开始。这有意义,尤其是当您从同一节点上传文件时。如果您决定以写入模式运行网关,则还可以以编程方式固定文件(默认情况下,它是只读的)。我们还允许用户指定自己的网关。 如果用户安装了IPFS Companion,他可以利用自己的节点运行。
BlogEvents.getPastEvents("PostAdded", { fromBlock: 0, filter: { author } }).then(events => { this.setState({ addedPosts: events.map(e => e.returnValues) }); });// ...getPost(gatewayIndex = 0) { this.fetchPostFromIpfs(gateways[gatewayIndex]) .catch(() => this.retry(gatewayIndex)) }
“如何将JSON文件存储在IPFS上”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。