IPFS身份管理和初始化本地仓库

IPFS身份管理和初始化本地仓库

由于IPFS网络是没有中心服务器的,各个节点之间的数据传输是需要识别各个节点的,并且要求各个节点的ID是唯一的,如果没有一定的生成规则,就带来了挑战。在IPFS中,IPFS节点ID是这样规定的。

1。节点要自己生成一个基于PKI(https://en.wikipedia.org/wiki/Public_key_infrastructure)的秘钥对。

2.对密钥对中的公钥做hash也就是HASH(节点公钥),就得到了节点的ID

默认生成的节点秘钥配置放在文件夹:~/.ipfs/config ,如果你没有自定义IPFS_PATH的话。

例如我本机的

"Identity":{

    **"PeerID"**:**"QmQeJWckGKS9C56NtyvqA3APsq4gbtS8YwPnLTb9ZT3dd4"**,

    **"PrivKey"**:**"privateKey"**

},

说明:~/.ipfs/config内容狠多,只是抽取identity

疑问:

这里如果节点作恶了,我从新生成一对密钥对就OK拉 !!!怎么办?

节点ID的使用,当两个节点需要通信的时候

1.交换两个节点的公钥

2.检测HASH(节点公钥)是否等于节点ID

3.如果检测不相等,就退出。

IPFS command 结构

IPFS每一个命令的结构大致如下

[图片上传失败...(image-f0edd7-1532334776759)]

IPFS 初始化流程

初始化命令

ipfs init

命令代码分析,主要入口文件:/Users/zhang/go/src/github.com/ipfs/go-ipfs/cmd/ipfs/init.go

init命令运行的时候

1.在postRun中检测是否配置文件所在的repo在是否存在repo.lock文件,有就代表ipfs的deamon进程存在,就退出(代码init.go 61行)

[图片上传失败...(image-7a1152-1532334776759)]

2.根据输入的options参数(可选参数中值得注意的是--bits,指定生成的秘钥的长度,默认2048 ,profile,指定生成的配置文件名称),执行doInit方法.

A。 在doInit先检测IPFS所在文件系统的读写权限。

B。 检测fsrepo是否存在了节点config文件

C。如果没有存在config,执行初始化流程如下:

细节:加密秘钥长度必须最少是2048,如果太小报错

a。调用libp2p-crypto库的GenerateKeyPair生成密钥对,加密方法RSA。其中私钥使用base64.StdEncoding.EncodeToString方法转换为字符串。公钥调用go-libp2p-peer的IDFromPublicKey方法得到字符串x,最终字符串x调用libp2p的IDB58Encode方法编码为字符串hash,这个hash就是节点ID

b。读取启动节点,也就是bootstrap peer,这些节点决定了本地节点启动的时候链接谁的问题。默认系统默认硬编码了如下节点。这些节点由IPFS官方来维护。

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="edtp" data-linenum="1">var DefaultBootstrapAddresses = []string{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="tcHw" data-linenum="2"> "/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="iuye" data-linenum="3"> "/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="vaLq" data-linenum="4"> "/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="rWC5" data-linenum="5"> "/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="NZGE" data-linenum="6"> "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="RltB" data-linenum="7"> "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="T416" data-linenum="8"> "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="M0Pc" data-linenum="9"> "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="nqTZ" data-linenum="10"> "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="3AWr" data-linenum="11"> "/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="b9pj" data-linenum="12"> "/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="9h5K" data-linenum="13"> "/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="NwDv" data-linenum="14"> "/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="DABt" data-linenum="15">}</pre>

c。读取数据存储默认配置文件DefaultDatastoreConfig,代码: src/github.com/ipfs/go-ipfs/repo/config/init.go 25行。

数据存储

数据存储是数据存储和数据库访问的通用抽象层。它是一个简单的API,其目的是使应用程序开发以数据不可知的方式进行,允许在不改变应用程序代码的情况下无缝地交换数据存储。因此,您可以利用具有不同强度的不同数据存储,而无需将应用程序在整个生命周期内提交给一个数据存储。

代码库

https://github.com/ipfs/go-datastore

配置文件如下

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="sA3L" data-linenum="1">func DefaultDatastoreConfig() Datastore {</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="OGvo" data-linenum="2"> return Datastore{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="xdl4" data-linenum="3"> StorageMax: "10GB",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="gX4x" data-linenum="4"> StorageGCWatermark: 90, // 90%</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="KFmk" data-linenum="5"> GCPeriod: "1h",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="axEP" data-linenum="6"> BloomFilterSize: 0,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Gg72" data-linenum="7"> Spec: map[string]interface{}{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="gRjH" data-linenum="8"> "type": "mount",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="6KDW" data-linenum="9"> "mounts": []interface{}{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="qm6h" data-linenum="10"> map[string]interface{}{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="HTM0" data-linenum="11"> "mountpoint": "/blocks",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="JYuT" data-linenum="12"> "type": "measure",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Cj74" data-linenum="13"> "prefix": "flatfs.datastore",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="QUK9" data-linenum="14"> "child": map[string]interface{}{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="skQk" data-linenum="15"> "type": "flatfs",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="ZBtd" data-linenum="16"> "path": "blocks",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="ZajB" data-linenum="17"> "sync": true,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="A7it" data-linenum="18"> "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="ZNCE" data-linenum="19"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Ptdr" data-linenum="20"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="mVIt" data-linenum="21"> map[string]interface{}{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="okWv" data-linenum="22"> "mountpoint": "/",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="XMu2" data-linenum="23"> "type": "measure",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="qPBJ" data-linenum="24"> "prefix": "leveldb.datastore",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="sQ5z" data-linenum="25"> "child": map[string]interface{}{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="nvjh" data-linenum="26"> "type": "levelds",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="jIFh" data-linenum="27"> "path": "datastore",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="7z4Z" data-linenum="28"> "compression": "none",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Eub7" data-linenum="29"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="H74N" data-linenum="30"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="nEy1" data-linenum="31"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="s3Ji" data-linenum="32"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="XJa2" data-linenum="33"> }</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="oM5x" data-linenum="34">}</pre>

默认存储空间10G,每小时一次GC,挂载点2个,一个是leveldb一个是flatfs,应该也是可以配置的。

d。读取本地地址默认配置,代码位置 src/github.com/ipfs/go-ipfs/repo/config/init.go 101行。

配置如下

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="Emy3" data-linenum="1">func addressesConfig() Addresses {</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="tHh7" data-linenum="2"> return Addresses{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="0vxN" data-linenum="3"> Swarm: []string{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="FDP1" data-linenum="4"> "/ip4/0.0.0.0/tcp/4001",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="aQsW" data-linenum="5"> // "/ip4/0.0.0.0/udp/4002/utp", // disabled for now.</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="lDIE" data-linenum="6"> "/ip6/::/tcp/4001",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="unRJ" data-linenum="7"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="msYH" data-linenum="8"> Announce: []string{},</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="aUkp" data-linenum="9"> NoAnnounce: []string{},</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="k3hq" data-linenum="10"> API: "/ip4/127.0.0.1/tcp/5001",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="KlhJ" data-linenum="11"> Gateway: "/ip4/127.0.0.1/tcp/8080",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="RiJh" data-linenum="12"> }</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="Ynce" data-linenum="13">}</pre>

可见,本地Swarm监听4001端口,使用这个端口和其他节点通信。支持IPV4和IPV6,默认不支持UDP方式。本地Api网关,127.0.0.1:5001 ,本地资源网关127.0.0.1:8080 。

e。配置组播配置

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="Puog" data-linenum="1">Discovery: Discovery{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Uigh" data-linenum="2"> MDNS: MDNS{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="gIHG" data-linenum="3"> Enabled: true,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="1NSa" data-linenum="4"> Interval: 10,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="JH7j" data-linenum="5"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="ANOC" data-linenum="6">},</pre>

使用MDNS协议来组网。在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口、包格式和操作语义。具体:https://www.cnblogs.com/yuweifeng/p/6409182.html

f。设置路由

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="qCNI" data-linenum="2">Routing: Routing{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="KBZP" data-linenum="3"> Type: "dht",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="5tlX" data-linenum="4">},</pre>

g。设置挂载点

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="fi60" data-linenum="1">Mounts: Mounts{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="FUhl" data-linenum="2"> IPFS: "/ipfs",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="qy2N" data-linenum="3"> IPNS: "/ipns",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="IoNJ" data-linenum="4">},</pre>

h。设置资源网管headers等信息

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="Gh9w" data-linenum="1">Gateway: Gateway{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="WCrQ" data-linenum="2"> RootRedirect: "",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="ScaG" data-linenum="3"> Writable: false,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="aBpD" data-linenum="4"> PathPrefixes: []string{},</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="AegP" data-linenum="5"> HTTPHeaders: map[string][]string{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Rbr9" data-linenum="6"> "Access-Control-Allow-Origin": []string{"*"},</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="HBwW" data-linenum="7"> "Access-Control-Allow-Methods": []string{"GET"},</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Ji5k" data-linenum="8"> "Access-Control-Allow-Headers": []string{"X-Requested-With", "Range"},</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Oa9W" data-linenum="9"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="9HxT" data-linenum="10">},</pre>

i。读取和设置swarm配置

<pre class="ql-syntax ql-authorBlock-13003047 first-line ql-long-13003047" spellcheck="false" line="voQp" data-linenum="1">Swarm: SwarmConfig{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="yQZK" data-linenum="2"> ConnMgr: ConnMgr{</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="FHMs" data-linenum="3"> LowWater: DefaultConnMgrLowWater,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="4rAh" data-linenum="4"> HighWater: DefaultConnMgrHighWater,</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="v54f" data-linenum="5"> GracePeriod: DefaultConnMgrGracePeriod.String(),</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="Vn1k" data-linenum="6"> Type: "basic",</pre>

<pre class="ql-syntax ql-authorBlock-13003047 ql-long-13003047" spellcheck="false" line="DCuL" data-linenum="7"> },</pre>

<pre class="ql-syntax ql-authorBlock-13003047 last-line ql-long-13003047" spellcheck="false" line="G4R3" data-linenum="8">},</pre>

D。解析配置文件

E。真正调用:fsrepo.Init(repoRoot, conf) 代码:161行。

a。写入C步骤生成的config文件到repo路径下面

b。初始化datastore空间

c。在repo下面写入版本WriteVersion

F。如果参数默认,调用addDefaultAssets写入默认readme文件到本地repo

到此为止,infs init 流程结束。

Multihash

https://github.com/multiformats/multihash

https://multiformats.io/multihash/#implementations

为何要有multihash?

本质上为了升级方便,现有的各种加密算法,不能保证以后不出问题。第三方如果依赖于使用的hash算法的名字和长度,以后升级就会带来各种各样的问题。为此,multihash就出来了,它采用TLV (type-length-value) 的方式抽象了Hash的使用~ 解决了依赖于hash 函数和 长度的问题。

在IPFS中使用multihas的地方主要是ipfs object分块和地址这里。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容