|
|
本帖最后由 赤膊医数 于 2021-4-22 23:41 编辑
- c3 e3 S& [, b: h5 M. L7 q! a1 G2 w& w, |4 s
2018年,最火爆且值得期待的区块链项目莫过于EOS和IPFS。1、IPFS简介- IPFS是什么; t6 i. c5 j# _/ V _; }
星际文件系统IPFS(InterPlanetary File System)是一个面向全球的、点对点的分布式版本文件系统,目标是为了补充(甚至是取代)目前统治互联网的超文本传输协议(HTTP),将所有具有相同文件系统的计算设备连接在一起。原理用基于内容的地址替代基于域名的地址,也就是用户寻找的不是某个地址而是储存在某个地方的内容,不需要验证发送者的身份,而只需要验证内容的哈希,通过这样可以让网页的速度更快、更安全、更健壮、更持久。
( a8 W9 m% A y/ q7 M8 [ b& C以上内容来自巴比特官网介绍, y0 C. h0 W: W: b8 `
IPFS是基于区块链技术的去中心化存储网络,实现了永久性存储。
! k- t2 c, s' i! K9 q9 \ - IPFS的火热. O, s) D& y" \- `1 D
Filecoin ICO是迄今为止涉及金额最大的ICO,仅一小时就募集了接近2亿美元,打破ICO记录,成为2017年最火爆的区块链项目。IPFS项目吸引了世界各地数字货币投资者和互联网从业者的密切关注,2018年比较值得期待的是IPFS主网的上线。然而就在前段时间,官方公布说上线时间延期到年底。7 k/ [, |! L& Y6 C. r
注:Filecoin是IPFS激励层的加密数字货币(即代币),有点类似于以太坊平台上的以太币。8 a! b" H+ x* t7 X( c9 | m
IPFS官网:https://ipfs.io/
3 V1 H% l6 Z2 p" T5 `# iFilecoin官网:https://filecoin.io/; w7 k- }: S2 B! Z: i
- IPFS的应用案例% {9 E/ r% [! r1 x7 f
GitHub有两款开源项目,且有对应网址,分别是音乐播放器和视频播放器。
4 e; @6 L! i; X" B% n/ ^8 l6 Y
5 U* s9 k) i7 c8 [- K: E. r9 Y- IPFS音乐播放器/ h& \/ e. U$ P" G3 N
0 P4 A% @- I. g. K/ e/ l
2 [! h# N* ^( s3 b- y1 P1 o3 A
, @, o8 M. G$ o5 }' b7 q# ]1 a
+ {& C7 U7 c: \: d I3 dIPFS音乐播放器
/ G) n0 _1 l. y0 Y) y! J. \
6 k* X- J. k3 iIPFS音乐播放器网址:https://diffuse.sh/
' ]! b! w; H7 G. d- {9 aGitHub地址:https://github.com/icidasset/diffuse
~1 M# B+ X9 W7 G5 d' h4 | - IPFS视频在线播放器
9 i. H. g! r3 N
- ^8 z$ l3 L6 b
4 u2 A5 }' R! @7 y
1 L( Y/ G2 M- y' x! u; S. t6 h) M# j5 T# E2 y; x. l- p- G
IPFS视频在线播放器首页
- C1 k0 o: t, D' m5 }# ~3 Y6 m( e
; e3 a( T2 O; n, j4 \/ M7 R4 p7 B
- @1 T5 N ?; x6 Q0 T7 N
4 k+ Z- X: J6 C$ x
! E* c: S1 I0 }
0 {( c; Y* d1 k7 d% Z2 {IPFS视频在线播放器播放电影
1 L& w. o& ^# Y' ~) q8 J2 `- A) {- H- M; B* `
号称是国内第一个IPFS应用
4 c. [& p. u4 t7 j9 T. aIPFS视频在线播放器网址:http://www.ipfs.guide/& [% I' V p2 }( |
GitHub地址:https://github.com/download13/ipfstube" [+ g4 f3 ?$ d. [
可用于测试的电影视频Hash(这里只列举两部):7 ~" \" t X* w- `) Z! w
神秘巨星:QmWBbKvLhVnkryKG6F5YdkcnoVahwD7Qi3CeJeZgM6Tq68: M& h3 x2 r! s) L4 L9 D; o
盗梦空间:QmQATmpxXvSiQgt9c9idz9k3S3gQnh7wYj4DbdMQ9VGyLh3 C v& t$ L: F2 j" Q: E6 O1 M& ]; K/ h" _
2、IPFS的安装既然IPFS这么牛,有必要了解一下IPFS的开发,先从IPFS的安装开始。; Q0 d$ h: ?( Q
- IPFS Desktop
. q+ a$ w! s8 z# {5 Y; Q) y当然,可以直接安装IPFS节点桌面管理软件来体验一下。该软件可以方便地运行和管理自己的节点,查看IPFS节点资源信息,支持二次开发。该项目是Node.js编写的,已开源。1 B c: D+ f$ M8 h0 o
6 {" w! J! m, c$ x- y
- p, w- x- T7 B- m; {
6 T% h. g/ s# [, z4 k
) i, Q6 a5 N. k! ^IPFS节点桌面管理软件2 X2 T7 K1 B) l$ m
/ C$ _6 i. ?! K; M& B: qGitHub地址:
: R2 x2 T1 V3 E, P0 Y9 N4 Yhttps://github.com/ipfs-shipyard/ipfs-desktop
# [" f( M5 p. h2 P+ n% K S - Go-IPFS
# c& V( C# i- y; }- U进入IPFS的官网,找到并切换到"Install"页面,点击"Download IPFS for your platform",会跳转到如下网址(需要翻墙):: b* ~+ F6 n. x6 g
https://dist.ipfs.io/#go-ipfs
9 }: Z4 b* n0 U3 ?! d" w4 m, p) h# M& h7 \
9 | |% _4 X. _. { Y
5 _' p+ ?. p/ A7 K- v
下载Go-IPFS6 K# z. ?3 a/ H, n8 n* ^
6 k* A0 j* M6 r! e9 N如果打不开,可以试着去Github查看安装方法
7 G# P& a5 J1 uGitHub地址:https://github.com/ipfs/go-ipfs0 E( E( N- Q! c4 K! | d
将网页下载好的文件解压出来,下载的是"go-ipfs_v0.4.13_darwin-amd64.tar.gz",解压出来的是go-ipfs文件夹,
$ K* ]* y9 Y( t; H! Z* y然后打开终端,进入到go-ipfs文件夹根目录,复制ipfs文件到系统的bin目录,然后可以通过"ipfs version"来检查,操作如下:
1 I D1 w6 @1 ^8 ?wenzildeiMac:go-ipfs wenzil$ pwd/Users/wenzil/Desktop/study/go-ipfswenzildeiMac:go-ipfs wenzil$ lsLICENSE README.md build-log install.sh ipfswenzildeiMac:go-ipfs wenzil$ cp ipfs /usr/local/bin/ipfswenzildeiMac:go-ipfs wenzil$ ipfs versionipfs version 0.4.13
- _7 J! r/ _+ }7 ~ 3、IPFS节点的创建、查看和启动以下是安装官网的Go-IPFS步骤下实验的
( l: H- s" T; n+ a7 @- 创建节点
0 ?& e9 ^& c/ z- A' @进入到当前用户的根目录,并使用"ipfs init"命令创建节点,可以用"open ./"打开创建节点生成的".ipfs"目录。0 w' w3 r% ^ Y! L
wenzildeiMac:go-ipfs wenzil$ cd ~/wenzildeiMac:~ wenzil$ pwd/Users/wenzilwenzildeiMac:~ wenzil$ ipfs initinitializing IPFS node at /Users/wenzil/.ipfsgenerating 2048-bit RSA keypair...donepeer identity: QmWH4xmGBznY9CJ4SjxpxWqGwMwrFtPdjgeweLCfJxW8j9to get started, enter: ipfs cat /ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readmewenzildeiMac:~ wenzil$ cd .ipfswenzildeiMac:.ipfs wenzil$ open ./
' S3 D/ ]* V1 O! r6 |- d
+ G3 v, V# }) S0 P& V5 F8 k
8 `1 V8 t J( f. [' }4 I" M v P7 W; g3 i. K0 ^
IPFS节点的创建
7 E3 Z4 V3 S% V4 ~4 u
7 \5 V! Z; R9 ]7 d# C$ u- 查看节点id5 n, q' Y0 C) B) s' b5 f
wenzildeiMac:.ipfs wenzil$ ipfs id{ "ID": "QmWH4xmGBznY9CJ4SjxpxWqGwMwrFtPdjgeweLCfJxW8j9", "PublicKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt98O5zNptBtmSF6xYdOHAMunQsXE9rAmgqBXVPLJk+AoaBjNiAipB+sTXKwaj8stp9c3iuSzz10+dyYI38bq4TPDCsHnQ3PjKSgZwEaT0M6pJhGqJcSbLY57CjQOEwgFe+tw3b4hcoDvvNJMG0dZZg1r9xnfevBz0DNewlj2vtviSTQL6r/ZXlD04GsytxTSQ2pzMJTG3QmYyokeZ37DT7Vwa+IJjDCiDJC5BlZ204zunZBx3tqWUn2Hr2NtEX+4YDdX4SBHa0ZDNqZmzLRe5YlAXjVI0ONHs+BVsC1v1L5we52iSYCSgVHoxRP/pa9EZdHMvgs9QeAa5jO90yxgTAgMBAAE=", "Addresses": null, "AgentVersion": "go-ipfs/0.4.13/", "ProtocolVersion": "ipfs/0.1.0"} - 修改IPFS默认存储空间5 I" f5 g( s5 \% R: k! ~6 j: j
存储节点默认存储大小为10G,如果你想修改存储空间,可以修改config配置文件,找到StorageMax并修改4 ~! w3 [' a& h& t) s. a6 J+ b
wenzildeiMac:~ wenzil$ export EDITOR=/usr/bin/vimwenzildeiMac:~ wenzil$ ipfs config edit
/ B6 X/ B& @: u: j2 P1 r F5 q
5 r; q; G7 r# \) d
6 _6 w( d1 x' }$ g. Q修改IPFS默认存储空间
4 b% p0 }) H2 G( T C
. o2 I( p5 i1 ~% }- M8 o8 K/ ] - 启动和同步节点服务器
! d8 H/ U9 q, Q0 Q, X3 L. R执行"ipfs daemon"命令,可以同步节点数据到IPFS网络。
; B9 P) {8 M! f' YwenzildeiMac:.ipfs wenzil$ ipfs daemonInitializing daemon...Adjusting current ulimit to 2048...Successfully raised file descriptor limit to 2048.Swarm listening on /ip4/127.0.0.1/tcp/4001Swarm listening on /ip4/192.168.1.100/tcp/4001Swarm listening on /ip6/::1/tcp/4001Swarm listening on /p2p-circuit/ipfs/QmWH4xmGBznY9CJ4SjxpxWqGwMwrFtPdjgeweLCfJxW8j9Swarm announcing /ip4/100.64.9.179/tcp/55898Swarm announcing /ip4/127.0.0.1/tcp/4001Swarm announcing /ip4/192.168.1.100/tcp/4001Swarm announcing /ip6/::1/tcp/4001API server listening on /ip4/127.0.0.1/tcp/5001Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8082Daemon is ready
3 ^/ B$ h! v3 F 4、IPFS运行体验- IPFS查看ReadMe7 R- N4 U. ?. t' q. a; `, T0 U8 R
可以回去查看执行"ipfs init"命令的时候,返回的内容。打开一个新的终端,操作如下:
' b# \+ G! m- X% E# o* o' PwenzildeiMac:~ wenzil$ ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readmeHello and Welcome to IPFS!██╗██████╗ ███████╗███████╗██║██╔══██╗██╔════╝██╔════╝██║██████╔╝█████╗ ███████╗██║██╔═══╝ ██╔══╝ ╚════██║██║██║ ██║ ███████║╚═╝╚═╝ ╚═╝ ╚══════╝If you're seeing this, you have successfully installedIPFS and are now interfacing with the ipfs merkledag! -------------------------------------------------------| Warning: || This is alpha software. Use at your own discretion! || Much is missing or lacking polish. There are bugs. || Not yet secure. Read the security notes for more. | -------------------------------------------------------Check out some of the other files in this directory: ./about ./help ./quick-start <-- usage examples ./readme <-- this file ./security-notes - Web管理界面
' B& G& n+ q( zIPFS节点服务器启动后,可以用浏览器访问:http://localhost:5001/webui1 K5 A$ E2 `; v9 W) X0 ~
有本地配置、节点连接、本地节点文件等信息,如图:
% q" h# Q8 n+ a$ r9 ?5 P
+ q. T+ `) z$ T+ M. J9 h; r' c+ z. B
+ d# y! r' i0 ?8 B6 I6 d
& w: w. c- ^( b% }$ a2 A6 M! ZIPFS的Web管理界面' a0 s& }8 x, d, D8 U. w
* K1 G+ j; l% O4 a8 x( O- p
2 p; \( F; z" Y- O, I( s. d3 R$ v3 s* k
5、设置跨域资源共享当我们在前端通过js接口操作ipfs时,会遇到跨域资源访问问题,可以在终端执行以下配置来解决:& H4 F; Y( z6 M0 ~. U" S
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT","GET", "POST", "OPTIONS"]'ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials '["true"]'ipfs config --json API.HTTPHeaders.Access-Control-Allow-Headers '["Authorization"]'ipfs config --json API.HTTPHeaders.Access-Control-Expose-Headers '["Location"]'6、IPFS的基本操作6.1 添加单个文件到IPFS节点- 新建文件5 S! I# M; `! X* U" T( c4 P
wenzildeiMac:ifps_test wenzil$ vi test.txtwenzildeiMac:ifps_test wenzil$ cat test.txt IPFS测试文件 - 添加文件到IPFS节点1 {% i8 [2 f% @; h" m9 n
wenzildeiMac:ifps_test wenzil$ ipfs add test.txt added QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab test.txt添加文件到IPFS节点后,返回了文件的哈希值
" C" \2 _% V/ ^* @- s7 a+ a. G - 查看IPFS节点的文件
/ x3 U0 H$ ]9 k$ @; t& Q$ N+ D6 MwenzildeiMac:ifps_test wenzil$ ipfs cat QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2AbIPFS测试文件注意:此时的文件只是添加到了本地的IPFS节点,读取的是本地数据,可以通过如下网址查看。) D# J. w0 ?& r7 `8 b# H) w
http://localhost:8080/ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab
5 c: U& h- m- p通过"ipfs daemon"命令启动节点服务器,会将本地节点文件同步到外网,同步成功后,这时就可以访问如下网址来查看(如果访问失败,试着翻墙看看)。
+ t! l& C) f1 r) S' zhttps://ipfs.io/ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab% i- K7 r$ ]( ?7 P7 d( h3 W9 j+ }
0 n# L; o: O' Q* t
( K% E$ x, r% k
7 v# l* I' ]: j0 r查看IPFS文件内容, i4 w# e4 u4 R. y9 t3 y
( t) v( X$ |: q1 ` Y# ~) g8 _如果访问成功的话,说明已经存储到IPFS网络中。目前IPFS网络暂未加入代币Filecoin机制,所以存储读取文件免费,速度也比较慢。4 Z8 I7 ~# C H; O; C( F
- 下载IPFS节点的文件
; H( E" P+ k4 cwenzildeiMac:ifps_test wenzil$ ipfs get QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2AbSaving file(s) to QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab 25 B / 25 B [========================================================] 100.00% 0s查看当前目录,发现多了一个"QmSV..."的文件"
+ G0 ?, }' x' Z, L3 [! M5 X9 j" Q) A; k" z5 k8 l( B6 f
' X K- T* R" p3 C" o K! E2 m
) R9 x) E9 B2 L; A R3 D
. i" `: x) ^. b- r7 e0 F
下载IPFS节点的文件% F( q0 G1 C3 ^8 ^4 h. X5 f( }* J5 n& L
' j2 Z0 s# F" f: k( x: I B
. p! Y$ _, n) U* d7 w 6.2 创建文件夹存储文件- ipfs命令新建文件夹0 p- f0 L+ _% H
wenzildeiMac:ipfs_test wenzil$ pwd/Users/wenzil/Desktop/study/ipfs_testwenzildeiMac:ipfs_test wenzil$ ipfs files mkdir /wenzilwenzildeiMac:ipfs_test wenzil$ ipfs files cp /ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab /wenzil/test.txtwenzildeiMac:ipfs_test wenzil$ ipfs files lstestwenzilwenzildeiMac:ipfs_test wenzil$ ipfs files ls /testwenzilwenzildeiMac:ipfs_test wenzil$ ipfs files rm -rf /testwenzildeiMac:ipfs_test wenzil$ ipfs files lswenzilwenzildeiMac:ipfs_test wenzil$ ipfs files ls /wenziltest.txtwenzildeiMac:ipfs_test wenzil$ ipfs files read /wenzil/test.txtIPFS测试文件注:"ipfs files rm -rf /文件夹名"可以删除文件夹。
+ U6 u$ n- c8 Z/ |+ M! Z( w! w0 \8 b' _: P( t" C, B
6.3 IPFS上传文件夹- ipfs命令添加文件夹% T- V: f/ O$ l( D: q" x* g
先在本地创建一个文件夹和对应文件,如图:
. M- U. }. ^! o- O- G
0 K7 G& G, p* p! s- B5 Z" ^ T& r
5 L2 P0 k3 ^( f; x+ a. i/ c- w4 E
r+ D) E4 J& A( E0 X3 o
本地创建文件夹及文件' v3 C( x' l1 c* g$ ?
/ [2 M) x6 F* D. b, M" _1 I- o
然后通过"ipfs add -r 文件夹"命令添加整个文件夹
1 v U. r% U3 X: a, L wenzildeiMac:ipfs_folder wenzil$ pwd /Users/wenzil/Desktop/study/ipfs_folder wenzildeiMac:ipfs_folder wenzil$ ls portrait.jpeg readme.txt wenzildeiMac:ipfs_folder wenzil$ cd .. wenzildeiMac:study wenzil$ pwd /Users/wenzil/Desktop/study wenzildeiMac:study wenzil$ ipfs add -r ipfs_folder/ added QmbHptfJfyuGAZxstFYgAVfz33cytR1seTD3ZabBSDd899 ipfs_folder/portrait.jpeg added QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQv T ipfs_folder/readme.txt added QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj ipfs_folder wenzildeiMac:study wenzil$ - 查看文件夹的文件内容
. [, F: _* c: c/ R4 K/ j3 I! @( swenzildeiMac:study wenzil$ ipfs cat QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT 我是区块链开发小白,请大家多多赐教,谢谢。欢迎阅读我的区块链系列文章,简书地址:https://www.jianshu.com/u/5f809ab3698cwenzildeiMac:study wenzil$ ipfs cat /ipfs/QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT我是区块链开发小白,请大家多多赐教,谢谢。欢迎阅读我的区块链系列文章,简书地址:https://www.jianshu.com/u/5f809ab3698cwenzildeiMac:study wenzil$ ipfs cat /ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj/readme.txt我是区块链开发小白,请大家多多赐教,谢谢。欢迎阅读我的区块链系列文章,简书地址:https://www.jianshu.com/u/5f809ab3698c - 查看IPFS对应文件夹
0 {" b, s! @- q访问文件夹对应的IPFS地址:8 ~7 Q- Y4 m. A
https://ipfs.io/ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj
; W" H8 H$ b# S3 w6 `第一次访问的时候,需要同步数据到IPFS网络,等待时间有点久,慢到让你以为同步失败了。
3 c# u2 O( X4 l" Y1 i7 s6 c
7 ^9 A2 G5 Q- l" h' Q! G
0 y- k% t, C7 V* q3 ~
, N: ^% M6 V, D* C9 c查看IPFS对应文件夹
$ B/ [* j9 }5 Q
( |3 }7 `' b! ^" I0 {访问文件夹对应的文件,如看到图片文件,访问ipfs网关:4 \% t9 p P5 W8 D
https://ipfs.io/ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj/portrait.jpeg
! D% t, D& h$ g$ `/ ~) K! T- t+ V* h; w/ z9 N* `, P
! _5 b5 m, v; h9 \! A' I1 [
) ?" F) q' n" h5 b. Q& z5 _
查看IPFS文件夹对应文件
: J/ p( B3 ]* |+ d. V2 z# R! I' c& B& f" q' u1 K( P
或者通过文件的Hash来访问,如访问txt文件的地址:2 P4 e M2 r% r
https://ipfs.io/ipfs/QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT# z; f9 Z) ~- [' M# X1 y1 [4 j& W
) @* {2 b0 c0 d
! Q+ M$ d; D) j0 [: {7 ~! o$ E$ b& P# e# x
通过文件Hash访问查看( N# s! ~& N! n) v; Q! \, i& P7 a
3 w% g- ^+ L! }/ `+ u
- c5 n; ?* }' n* M' D' Y 6.4 添加简单网页到IPFS节点- 网页效果和项目结构
& L% M5 H+ Z: e实现一个简单的实时显示系统当前时间的网页,效果如图:
- B- N3 ]" g- `1 x w! q' g+ C1 C3 L. Q7 x0 @
) M$ k: P [) I' q n7 I
2 g; B, |9 _' w, S" z/ u
3 x( [" _7 ?- M, F! U, OIPFS添加简单网页9 w/ r) ?; h4 Q' m
- n' t8 L( }/ _- @8 I) {工程结构如图:
* s) h) D, D$ G' I( H' ^1 ~& S( J0 r- N& v5 _
: ]8 {0 H( y5 {9 H! K, H8 d
, B$ ?. I( j' _" m2 ^8 ?; @, e5 d& C+ p7 {4 \5 m
网页工程结构- o- g# u3 f- N0 p) O. B% S1 e
8 q3 B5 ^, u0 F! E: F6 V4 N# J
实现代码比较简单,这里就不贴代码了。, C8 v A; `" k0 s0 ?* e
- ipfs命令添加文件夹/ m4 A# j0 p2 Y& ^
wenzildeiMac:study wenzil$ ipfs add -r ipfs_htmladded QmTj49dgFgFhfNRTUYyUSzk3puj7vvDoVsAynFrL7GAj1d ipfs_html/index.htmladded QmeHFBSyN9KqeZWKyKTWKYzDRU192YWDRjf6sLWFWhwk2z ipfs_html/styles.cssadded QmWkEfgL2pjo7n8b9YBCv4qwE77YWePkSscxiHQfPpwpkp ipfs_html/time.jsadded QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD ipfs_html记得要开启IPFS节点服务器进行数据的同步,可以使用"ipfs daemon"命令在新的终端窗口打开运行。
( {& ?8 b8 s- K, B. E2 J; G O7 R* ywenzildeiMac:~ wenzil$ ipfs daemonInitializing daemon...Adjusting current ulimit to 2048...Successfully raised file descriptor limit to 2048.Swarm listening on /ip4/127.0.0.1/tcp/4001Swarm listening on /ip4/192.168.6.31/tcp/4001Swarm listening on /ip6/::1/tcp/4001Swarm listening on /p2p-circuit/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrzSwarm announcing /ip4/127.0.0.1/tcp/4001Swarm announcing /ip4/192.168.6.31/tcp/4001Swarm announcing /ip6/::1/tcp/4001API server listening on /ip4/127.0.0.1/tcp/5001Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8082Daemon is ready - 访问ipfs对应文件
' M4 }* g# H5 C; o* I. |# t浏览器访问ipfs网关:; t1 M# n3 u) x& @1 n; E
https://ipfs.io/ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD/
; k; C, C7 K& d, g- M: H( @; l" A# [6 ^# H8 L, W* ^
# J% ?: H' ]9 D- ^) ?3 [
0 c, y- s) X$ V/ E1 [0 G' O
查看IPFS对应网页/ C) f: R3 b' o5 o4 N8 b9 a
/ I# n1 U# x) K; t5 i9 m: \2 b$ ]4 Q! |3 G; }) V/ H8 N9 }
6.5 IPNS绑定节点名- IPNS绑定节点操作! i4 @& l' x3 i; l1 E
每次修改文件内容后,文件的哈希值就会发生变化。对于网站而言,发布后可能还需要做修改,这时需要IPNS绑定节点名。每次更新网站内容后,重新publish一次更新发布到IPNS即可。& K: Q, [/ g. ]" y, x2 M$ D
刚才的html根目录的哈希值是QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD,操作如下:# }4 K) i1 x8 U) Q3 \
wenzildeiMac:study wenzil$ ipfs name publish QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDDPublished to QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz: /ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD - 查看当前节点
6 \/ w9 w# |2 _- i) ~wenzildeiMac:study wenzil$ ipfs id{ "ID": "QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "PublicKey": "CAASpg......", "Addresses": [ "/ip4/127.0.0.1/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip4/192.168.6.31/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip6/::1/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip4/14.xxx.xxx.xxx/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip4/61.xxx.xxx.xxx/tcp/20472/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz" ], "AgentVersion": "go-ipfs/0.4.13/", "ProtocolVersion": "ipfs/0.1.0"} 发现"ID"和上面"Published to"返回的节点一致,都是"QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz". V% k2 _) [$ M4 c3 i
- 验证节点
9 J+ c: M2 r0 A命令为:"ipfs name resolve 节点ID“
: N( W* j4 z! L% O; `wenzildeiMac:study wenzil$ ipfs name resolve QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz/ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD - 访问IPNS对应文件- H4 c. S$ B, F. m
浏览器访问ipfs网关:- W" u: j7 |) I D
https://ipfs.io/ipns/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz/! O1 V- c6 h. d) B% j; L( e; c
8 o C) } q# f% C. e* W& S
* j& ~; q; m3 Z; u9 x9 g
$ q. ?$ \; A8 Q; y5 l+ r5 E/ B, E: w2 K
查看IPNS对应网页
( c( O4 C. Z( {0 b E5 y/ ?# k
* _$ [% x# k8 ^/ K$ ^% ~7、IPFS与以太坊DApp开发实战- IPFS与以太坊DApp结合的好处
2 {. a. [8 y+ D: v在以太坊平台上,往区块链写入数据需要花费以太币,调用智能合约执行每一行代码的时候,都需要一定量的gas交易费。区块链存储大数据成本很高,而且不合理。% y9 A, z0 r: L! k C
可以先将文件存储到IPFS,然后得到文件的Hash存储到以太坊区块链中。读取文件的时候,从以太坊区块链中获取文件的Hash,再通过Hash来读取IPFS网络上的文件。/ p9 m: R! j' j0 K3 h! W" ]
使用官方提供的ipfs-api,可以很方便地在代码中操作节点将数据上传到IPFS,或者通过Hash从IPFS读取数据。
2 y) T# Z, T' s8 T" D& `( B# GTruffle框架提供了快速搭建包含以太坊智能合约的React项目,可以通过"truffle unbox react"创建工程,然后安装ipfs-api依赖库。于是,可以在前端方便地调用IPFS的接口来读取、上传文件。/ O4 O( Z1 V: N" E4 i h
truffle unbox react官网:
) g5 i8 d8 i0 }- w" X) r/ {http://truffleframework.com/boxes/react5 _! R5 Z; n1 [. @% R6 C
- IPFS与DApp开发实战
9 F+ ~6 W W& n/ L$ |' c9 X1 I话不多说,开始进入实战开发。. N3 A2 N6 v/ `* r0 d- x$ i6 s2 i
7.1 安装Truffle unbox react新建一个空目录"ipfs_dapp",然后执行安装命令
* D5 s8 O( r" J7 W6 i' T' \truffle unbox reactwenzildeiMac:ipfs_dapp wenzil$ pwd/Users/wenzil/Desktop/study/ipfs_dappwenzildeiMac:ipfs_dapp wenzil$ truffle unbox reactDownloading...Unpacking...Setting up...Unbox successful. Sweet! Commands: Compile: truffle compile Migrate: truffle migrate Test contracts: truffle test Test dapp: npm test Run dev server: npm run start Build for production: npm run build7.2 安装ipfs-apinpm install --save ipfs-apiwenzildeiMac:ipfs_dapp wenzil$ npm install --save ipfs-apinpm WARN deprecated bignumber.js@6.0.0: Custom ALPHABET bug fixed in v7.0.2react-box@0.1.0 /Users/wenzil/Desktop/study/ipfs_dapp├—┬ ipfs-api@22.0.0 │ ├—— async@2.6.1 │ ├—— big.js@5.1.1 │ ├—┬ bs58@4.0.1 │ │ └—— base-x@3.0.4 # ...... 省略N多行输出7.3 修改智能合约代码修改contracts目录中的"SimpleStorage.sol",修改后完整代码:
; c( B$ J0 V/ {- ^pragma solidity ^0.4.18;contract SimpleStorage { // 用于存储图片的哈希值 string storedData; function set(string x) public { storedData = x; } function get() public view returns (string) { return storedData; }} 修改"Migrations.sol"
9 b* c0 h# Z F$ w! H `6 Tfunction Migrations() public { owner = msg.sender;}修改为:constructor() public { owner = msg.sender;}7.4 编译智能合约truffle compilewenzildeiMac:ipfs_dapp wenzil$ truffle compileCompiling ./contracts/Migrations.sol...Compiling ./contracts/SimpleStorage.sol...Writing artifacts to ./build/contracts7.5 部署智能合约进入remix-ide,复制SimpleStorage.sol代码,然后切换到"Run"菜单,选择"Injected Web3"进行智能合约的部署6 @9 v0 x2 k' X t' N. b
; R: k1 N3 a- | H! o' ^
1 @) p, Z- G! v0 H4 Y! n; _
4 I! k+ v9 \* u5 I' P" bRemix-IDE部署智能合约
9 }0 s, d" ~1 X' S! }8 \ G1 W1 m1 a
z+ u5 @3 D( E4 k6 H9 `* k
3 l/ |, S3 R2 m5 e! m. C8 q
2 k* |0 [/ k/ r" L! C# k4 L3 k
Remix-IDE部署智能合约-确认
9 c8 o! M6 v* U+ x
N, f4 F; }2 |# V( V然后复制智能合约地址,App.js文件中会用到合约地址为:"0xb177d6cf6916f128c9931e610c63208d9c5a40f3"
" D0 I- U$ l9 {- C$ @' g5 O8 s7.5 修改App.js文件import React, {Component} from 'react'import SimpleStorageContract from '../build/contracts/SimpleStorage.json'import getWeb3 from './utils/getWeb3'import './css/oswald.css'import './css/open-sans.css'import './css/pure-min.css'import './App.css'const ipfsAPI = require('ipfs-api');const ipfs = ipfsAPI({ host: 'localhost', port: '5001', protocol: 'http'});const contract = require('truffle-contract')const simpleStorage = contract(SimpleStorageContract)let account;// Declaring this for later so we can chain functions on SimpleStorage.let contractInstance;let saveImageToIPFS = (reader) => { return new Promise(function(resolve, reject) { const buffer = Buffer.from(reader.result); ipfs.add(buffer).then((response) => { console.log(response) resolve(response[0].hash); }).catch((err) => { console.error(err) reject(err); }) })}class App extends Component { constructor(props) { super(props) this.state = { blockChainHash: null, web3: null, address: null, imageHash: null, isSuccess: false }}componentWillMount() { ipfs.swarm.peers(function(err, res) { if (err) { console.error(err); } else { // var numPeers = res.Peers === null ? 0 : res.Peers.length; // console.log("IPFS - connected to " + numPeers + " peers"); console.log(res); }});getWeb3.then(results => { this.setState({web3: results.web3}) // Instantiate contract once web3 provided. this.instantiateContract() }).catch(() => { console.log('Error finding web3.') })}instantiateContract = () => { simpleStorage.setProvider(this.state.web3.currentProvider); this.state.web3.eth.getAccounts((error, accounts) => { account = accounts[0]; simpleStorage.at('0xb177d6cf6916f128c9931e610c63208d9c5a40f3').then((contract) => { console.log(contract.address); contractInstance = contract; this.setState({address: contractInstance.address}); return; });})}render() { return ( <div className="App"> <div style={{marginTop:10}}>智能合约地址:</div> <div>{this.state.address}</div> <div style={{marginTop:10}}>上传图片到IPFS:</div> <div> <label id="file">选择图片</label> <input type="file" ref="file" id="file" name="file" multiple="multiple"/> </div> <button style={{marginTop:10}} onClick={() => { var file = this.refs.file.files[0]; var reader = new FileReader(); reader.readAsArrayBuffer(file) reader.onloadend = function(e) { console.log(reader); saveImageToIPFS(reader).then((hash) => { console.log(hash); this.setState({imageHash: hash}) }); }.bind(this); }}>开始上传</button> <div style={{marginTop:10}}>图片哈希值:{this.state.imageHash}</div> <button onClick={() => { contractInstance.set(this.state.imageHash, {from: account}).then(() => { console.log('图片的hash已经写入到区块链!'); this.setState({isSuccess: true}); }) }}>图片哈希写入区块链</button> { this.state.isSuccess ? <div style={{marginTop:10}}> <div>图片哈希成功写入区块链!</div> <button onClick={() => { contractInstance.get({from: account}).then((data) => { console.log(data); this.setState({blockChainHash: data}); }) }}>从区块链读取图片哈希</button> </div> : <div/> } { this.state.blockChainHash ? <div style={{marginTop:10}}> <div>从区块链读取到的哈希值:{this.state.blockChainHash}</div> </div> : <div/> } { this.state.blockChainHash ? <div style={{marginTop:10}}> <div>访问本地文件:</div> <div>{"http://localhost:8082/ipfs/" + this.state.imageHash}</div> <div>访问IPFS网关:</div> <div>{"https://ipfs.io/ipfs/" + this.state.imageHash}</div> <img alt="" style={{width: 100, height: 100 }} src={"https://ipfs.io/ipfs/" + this.state.imageHash}/> </div> : <img alt=""/> } </div>); }}export default App7.6 新建终端,执行"npm start"命令,结果如图:: ]# `( A9 V6 f6 @) T5 Y. H( S# n
/ w# y$ n* Y0 n! d& V
% u; l4 X, |$ i2 @7 n
npm_start& w- D( Q7 _! ^$ c
$ E8 K3 a- ^- X" O
会自动打开网页,然后上传一张本地图片,之后点击"图片哈希写入区块链"按钮
, P' x( a1 w8 K: C2 M
2 F0 i3 N p# n$ {0 K' [+ k: m
9 I' J4 V$ Y8 I7 _8 p& A
3 Q! m+ o4 x* r- c6 ^ P
运行结果1
1 |- ]. h2 {) c# A6 z$ x
9 J; r7 F/ \; t+ b4 ?1 K1 d最终效果如图:
+ \& p; C8 l! T) ?
. |7 z: L; R' I. v% h0 z
2 c8 q/ l8 z- A+ q/ {6 _
4 `9 L. G0 @* H! d9 T. K9 k5 C' t
# U' c$ O) i/ G& X* l3 m0 L! A I运行结果
; P- n1 I3 t: r0 F# a) { h
3 F6 H* e2 c1 l( y访问IPFS网关:. U$ S1 u X0 ^3 b5 h. P
https://ipfs.io/ipfs/QmbHptfJfyuGAZxstFYgAVfz33cytR1seTD3ZabBSDd899
) [ S8 b K# C7 ]' y8 v o发现图片已经成功写入IPFS,如图:6 m- ~6 p, y5 x- L4 R
4 i' D6 Z4 T( d/ `
/ ^" r; I( p/ p* L9 I' Z7 q5 C0 V* C
: j \% y/ k$ G [$ h Z- ?4 G
8 u$ G% y% d- B0 l, {运行结果3
4 q: _$ d- p+ f0 G% s2 B! X& G1 a2 ?' }
备注:本地IPFS网关端口默认为8080,我的电脑上端口冲突了,系统自动修改为8082。# `! f7 |! i* q8 D& y+ |% e$ S; g
搞定,收工。
( i: x5 X/ n* P0 B5 }PS:刚入坑的小白,很多不懂,还请各位大佬多赐教,谢谢!
3 ] m4 l9 J: B3 p; R% S
6 C. I" X( a/ T. m' ~
|
|