科普 | 再談:以太坊是什么

大概整整兩年前,我從一篇介紹“區塊鏈”技術的文章里知道了“以太坊”這個項目,當時當然沒想到它會對我個人產生如此大的影響。在其后這兩年時間里,我投入了大量的時間和精力來學習它、研究它,做了多次技術分享,甚至還寫了講解智能合約開發的書、開發了關于智能合約開發的在線課程;所以不管未來我們各自的走向如何,以太坊都已經在我生命中留下了重重的一筆。在我們相識兩周年之際,我覺得我總該要寫點兒什么。

新年的這第一個月我過的很充實:只感了兩次冒,每次大概半個月……。本來我是計劃在月底前寫完技術專題“工程師眼中的比特幣和以太坊”的,可惜也無奈地再次被教育了:“年齡不是問題,但身體是問題。”所以臨近月底只能以這篇文章勉強交個作業吧。

2017 年底的時候,我曾在簡書發過一篇博客,介紹“以太坊是什么”,但那是一篇對以太坊 Homestead 官方文檔的翻譯稿節選??陀^地講,當時我本人對以太坊的理解也還不是非常深入透徹,所以這篇原創的“再談:以太坊是什么”還是有一些參考價值的,我相信這篇文章也許比一年前的那篇翻譯稿更好懂一些,而且真正講出了一些“本質性”的基本概念。
當然,這不是一篇 hardcore 的技術文章,我的初衷是基于我本人對以太坊的理解,從概念上給那些還不是很清楚地知道“以太坊是什么”的朋友做一個簡單的掃盲。這也是我寫這個新的技術專題的初衷:我希望讓更多軟件工程師能了解區塊鏈、了解智能合約,希望有更多的人能真正搞懂一些最基本的概念,并以此為契機深入到區塊鏈和智能合約的世界中。

因為本文的主體內容選自我的技術專題“工程師眼中的比特幣和以太坊”,所以文中對比特幣系統技術細節的引述可能會略顯突兀、缺少鋪墊;如果你對比特幣的技術細節還不了解,也可能會引起一些迷惑,對此我也表示歉意。不過我還是希望你能喜歡本文的內容和講解方式;此外如果能給我提供任何形式的反饋,我也將感激不盡。

完整閱讀本文約需要 15 到 20 分鐘。

時間已經來到了 2019 年 1 月,相信對很多人來講,“區塊鏈”這個詞恐怕已經不陌生了,并且大概也已經聽過“比特幣”的名號;不過,如果有人問你:“以太坊是什么”,你能夠很清晰、準確地給他解釋清楚嗎?

我想如果你看過“以太坊白皮書(Ethereum White Paper)”,你大概會用它的標題來回答這個問題:“A Next-Generation Smart Contract and Decentralized Application Platform”,翻成中文就是“下一代的智能合約和去中心化應用程序平臺”。沒錯,這很權威,也很準確。但是,我想即使對于軟件工程師來講,這個答案中引入的兩個新概念“智能合約”和“去中心化應用程序”其實也并不那么“一目了然”。顯然,我們不應該用未知的概念去解釋其他未知的概念。不過我想這仍然稱得上是一個不錯的開端,就讓我先沿著這個思路聊聊“智能合約”和“去中心化應用程序”吧。

什么是智能合約

智能合約(Smart Contract)這個詞最初是由一位美國的計算機科學博士尼克薩博(Nick Szabo)在他 1997 年發表的一篇論文中提出來的。智能合約指的是一種基于計算機技術實現的,可以免除人工干預而自動執行、自動校驗、自動基于外部指令給出回應的具有交互性或者互操作性的合約;其本質是一種計算機程序。這個概念本身相對比較抽象,所以尼克薩博本人在后來的一些訪談中曾經用自動取款機或者自動售貨機來作為智能合約的物理實例;它們就是基于某些公開的、眾所周知的規則,能夠根據用戶的指令和實際業務數據的狀態給出可預期的回應的這樣一種應用程序。

比如我們去自動售貨機購買某種商品,我們先要選擇商品和購買數量,如果自動售貨機中庫存不足,它應該會給出相應的提示;如果庫存充足,它會提示用戶進行實際支付,比如用現金或者電子支付;如果支付金額不足,它會給出提示,并繼續等待,直到支付金額足夠或者用戶取消交易;如果支付金額足夠,它們就會吐出正確數量的商品,并進行找零。自動售貨機在這整個過程中對用戶操作的響應應該是確定的、可預測的、可自動完成的,當然也應該是正確的。那么能夠基于實際情況給出這些正確響應的程序,就可以認為是智能合約。

當然,其實這個過程并不“智能”,從某種意義講,也并不是“合約”。所以這個詞從其誕生開始就有一些爭議,尤其是它會給一些不明所以的用戶某種程度的誤解。從本質來看,所謂“智能合約”實際上只是一種可以基于某種狀態數據自動給出回應的應用程序而已。不過出于歷史原因,“智能合約”的叫法還是被業內接受并延用了下來。

智能合約有什么用

這里我僅舉兩個最簡單的例子來解釋智能合約的意義。

首先是一個租房合約的例子。比如我和房東訂立了一個租房合約,約定我每月付給房東 1000 元房租,合約期限為一年。在沒有智能合約的情況下,這個合約的履行是需要很多人工介入的,我付錢的動作必須由我主動完成;如果出現意外情況,也需要第三方的介入才能解決,比如中介機構的居間調停乃至民事訴訟、強制執行等等。而如果有一種無需信任的智能合約平臺,這整個過程就可以變為下面這樣:

我和房東可以在某個智能合約平臺上訂立一個智能合約,創建合約的時候,我將一年的租金鎖定到合約里,然后從訂立合約開始,每經過一個月,房東可以從合約中提取一個月的租金,直到合約期限完結或者經雙方確認中止合約,合約自動給我退回剩余未支付的租金。這樣的場景是可以在像以太坊這樣的智能合約平臺上簡單實現的,這整個過程無需任何第三方介入,并且可以保證執行的過程嚴格按照約定的條件完成。

請注意,這個過程是“無需信任(trustless)”的。也就是合約雙方不需要相互認識乃至相互信任,而是基于一種不可篡改、不可抵賴、不可逆轉的自動化的技術方案保證了整個過程的可信性,同時不需要任何第三方的介入。這就是智能合約帶來的最重要的特性。

當然,這個例子中的一些細節是和我們普遍采用的人工處理的方式有差異的:比如我要支付的一年的租金是需要在訂立合約時就要鎖定到合約里的,而不是可以像人工操作的方式那樣每月提供;又比如要中止合約時是需要雙方確認的,如果有一方故意不進行確認,那么合約會被鎖死,這需要事先考慮到,并在合約中設計相應的解決方法。不過即使存在實操上的差異,這種自動化的、不可抵賴的智能合約選項依然稱得上是一種進步。

第二個例子是一個簡單的保險。比如某地區的一個農民可以與某保險公司訂立一份合約,合約條款大概可以是這樣:該農民于今年 6 月 30 日前支付 x 元保險費給保險公司;如果今年 7 月到 9 月某地區的平均降雨量不足 100 毫米,則農民可以在 9 月 30 日之后得到 y 元的保險賠償;否則無需賠償。

這個保險,同樣可以用像以太坊這樣的智能合約平臺簡單地實現:農民和保險公司可以在 6 月 30 日之前訂立合約,農民將 x 元、保險公司將 y 元同時鎖定到這個合約中;在 9 月 30 日之后,農民或者保險公司都可以向合約申請執行;合約可以自動從無利益關系的第三方公共服務(比如氣象臺網站)獲取 7 月到 9 月的降水量信息;如果降水量低于 100 毫米,則將 x + y 元支付給農民,反之則將 x + y 元支付給保險公司。這整個過程同樣無需人工介入,可以基于智能合約自動完成。

這個例子中提到的“無利益關系的第三方公共服務”,通常是通過一種區塊鏈系統/智能合約平臺以外的獨立數據源來提供的。這是因為區塊鏈系統本身無法產生或者直接獲取某些特定的數據,比如天氣數據、股票價格等等,那么就需要獨立的“鏈外”數據提供方來提供具體的數據。這種提供鏈外數據的服務,也就是所謂的“預言機(Oracle)”。因為本文只是掃盲性質,這里不再具體展開了。

所以,從邏輯概念上看,智能合約可以理解為一種會經過“技術公證”的狀態存儲和狀態轉換(也就是程序執行),以此來確保這個過程“無需信任”。(稍后我會從技術角度來解釋這個概念。)

去中心化應用程序又是什么

在理解了智能合約的概念之后,再來理解去中心化應用程序就比較容易了。

目前的絕大多數 Web 應用,其用戶數據都是保存在由某個公司、組織或者個人控制的“服務器”或者“服務器組”之中的,這些應用中的絕大部分業務計算,也是由這些服務器或者服務器組來提供的;所以這種模式,可以認為是一種“中心化(centralized)”的模式。

那么“去中心化應用程序(Decentralized Application)”,也就是將數據保存到“基于點對點網絡的時間戳服務器(即區塊鏈)”這樣的,并不是由中心化的公司或組織控制的服務中,并且由這樣的“去中心化”服務來提供具體的業務數據計算能力的一種應用程序。“去中心化應用程序”也可以簡單地理解為是基于智能合約進行狀態追蹤和計算的一種應用程序。

這里的“基于點對點網絡的時間戳服務器”的說法是出自比特幣白皮書,這也是“區塊鏈”一詞的原始出處。

當然,對于一個應用程序來講,并不是所有運算都需要用智能合約來實現,通常也不應該這樣設計;而是應該根據業務需求,將那些需要做“全網公證”的狀態計算在智能合約中實現,來使應用程序獲得某些“無需信任”的可信性。

好了,在了解了智能合約和去中心化應用程序的基本概念之后,我相信你已經大概知道以太坊是什么了。這里再重復一下:以太坊就是一個智能合約和去中心化應用程序平臺。 不過,我還有第二種答案。請你稍安勿躁,讓我嘗試基于以太坊的總體設計思路和技術方案概要來慢慢為你揭曉。

以太坊的誕生

與比特幣不同,以太坊白皮書的作者不是匿名的,它的初稿是由 Vitalik Buterin 于 2013 年底完成的。Vitalik 在 1994 年出生于俄羅斯,后來隨父母移居加拿大,在寫出以太坊白皮書的時候,他只有 19 歲,剛剛從滑鐵盧大學大一輟學。不過,在他寫出以太坊白皮書之前,他已經是一個知名的比特幣研究者和寫作者,他也是在 2011 年創刊的世界上第一個加密貨幣期刊——Bitcoin Magazine 的聯合創始人。可以說,以太坊白皮書并不是像比特幣白皮書那樣“憑空出現的”。Vitalik 本人從 2013 年下半年就開始思考如何對比特幣的腳本系統進行擴展來支持“通用目的”的計算任務。

2013 年 12 月,Vitalik 完成了以太坊白皮書,并在小范圍內進行了分享,引起了一些業內人士的關注,其中就包括了“精通比特幣(Mastering Bitcoin)”一書的作者 Andreas M. Antonopoulos,但他當時在忙于寫作精通比特幣,所以并未直接參與以太坊創建初期的具體工作。真正在工程上幫助 Vitalik 實現了以太坊這個偉大構想的則是 Gavin Wood 博士。

Gavin Wood 博士是英國約克大學的計算機科學博士,在以太坊項目最初的兩年里,他是在工程上貢獻最大的人:他于 2014 年 1 月完成了以太坊的 PoC-1(即第一個概念驗證程序,也是以太坊的 C++ 客戶端的最初原型);隨后在 3 月發表了以太坊黃皮書(即以太坊協議的細節說明和技術手冊,是實現以太坊客戶端的基礎技術資料,在工程上具有極其重要的指導意義,它也是我們了解和學習以太坊協議技術細節的主要參考資料);同年 8 月公布了專門為智能合約開發而設計的高級語言 Solidity。

2015 年 7 月 30 日,以太坊主網正式上線,創世區塊產生,世界上第一個成功的公共智能合約平臺才真正誕生。

以太坊的開創意義在于:它借鑒了由比特幣系統創造出來的“通過工作量證明算法達成共識的、基于點對點網絡的時間戳服務器”(也就是所謂的“區塊鏈”),構建出了一種可以執行“通用目的”計算任務的基礎設施,將“區塊鏈”的可編程性提升到了一個新的高度;創造出了真正的“智能合約”平臺。

區塊鏈范式

從技術層面講,我們可以把類似于比特幣這樣的、通過分布式共識進行“公證”的公共賬本系統(也就是所謂的“區塊鏈”)抽象地理解為一個“狀態轉換系統(state transition system)”。這種系統會維持一個“全局的狀態”(我們用 S 來表示),然后通過系統中發生的“交易”(我們用 tx 來表示)來進行相應的狀態轉換以達到一個“新的全局狀態”(我們用 S' 來表示)。那么這種狀態轉換就可以抽象地表示為:Apply(S, tx) = S',其中的 Apply 即“狀態轉換函數”。

下圖是比特幣中的狀態轉換示意:

比特幣中的狀態轉換

圖中用 <txid>:<output_index> 的形式來表示某個 UTXO:其中 txid 即交易哈希,用來標識某個具體的交易;output_index 即交易生成的輸出(UTXO)的索引。

UTXO,即 Unspent Transaction Output,是基于比特幣的數據模型產生的一個術語。比特幣中的交易都是由若干輸入(Input)和若干輸出(Output)組成的。按照協議約定,一個輸入必定是某個歷史交易的某個輸出的引用,通過在輸入中包含特定的“解鎖腳本(unlocking script)”來對歷史交易的輸出中指定的“鎖定腳本(locking script)”進行解鎖,以此來“消耗/使用(spend)”相應的輸出。那些未被任何“輸入”引用過的“輸出”就是 UTXO。

如上圖所示,比特幣中的交易會消耗/使用若干 UTXO,并通過合并和拆分來生成等量的新的 UTXO。上圖中的實例就是通過 7b53ab84 這個交易的第 1 個輸出和 3ce6f712 這個交易的第 2 個輸出來生成了 3 個新的 UTXO,即 bb75a980 這個交易(也就是上圖中這個交易)的輸出 0、1 和 2。于是,系統整體的狀態,就從 5 個 UTXO 變為了 6 個 UTXO。

所以,比特幣系統其實就是一個對當前系統中所有可用的 UTXO 的狀態記錄,它通過一個具體交易來對當前可用的若干 UTXO 進行合并和拆分來生成新的 UTXO,并將系統狀態轉換為新的 UTXO 集合;同時,這個過程是在一個點對點網絡中進行“全網公證”的。

考慮到像比特幣這樣的“區塊鏈”系統是以區塊為單位來打包記錄交易的,我們其實已經可以對“區塊鏈”下一個技術上的定義了:“區塊鏈”,其實就是一個通過交易來觸發狀態變動,并以區塊為單位來記錄狀態變動的狀態轉換系統。剛剛介紹過的狀態轉換范式 Apply(S, tx) = S',也就是所謂的“區塊鏈范式(blockchain paradigm)”。

請注意,這是一個通用的范式,它適用于比特幣,也適用于以太坊,并且同樣適用于其他類似于比特幣和以太坊這樣的基于“區塊鏈”的分布式共識賬本系統。而不同的區塊鏈系統的差別就在于如何表示系統中的狀態以及如何定義狀態轉換函數(也就是交易)。

那么,對于目標是要實現一個“智能合約平臺”的以太坊來講,使用比特幣的 UTXO 模型來保存系統狀態和構造交易數據可行么?

以太坊的“賬戶模型”和“存儲”

在剛剛介紹智能合約的概念時我提到過:智能合約其實可以看作是一種用于記錄和修改“狀態”的應用程序。從計算機科學的角度來看,這其實就是“狀態機(state machine)”。每個智能合約,都可以看作是一個自定義的狀態機。那么對于“智能合約平臺”而言,最關鍵的特性就是允許用戶自定義狀態機,同時保證這些自定義狀態機可以自動地、正確地、不可篡改地執行,且執行過程應該被進行“技術公證”,以此來保證合約參與方之間“無需信任”。

很明顯,“技術公證”的問題已經被比特幣解決了:我們只需要把所有自定義狀態機的狀態數據保存到區塊鏈上,通過工作量證明算法達成共識,實際上就實現了對自定義狀態數據的“全網公證”。但是,如何將“自定義狀態”保存到區塊鏈上呢?比特幣的 UTXO 模型能夠做到么?

簡單地說,參考業內到目前為止的研究和工程實踐成果,基于 UTXO 模型來保存自定義狀態數據大概是可行的,但相對而言會非常復雜,或者需要一些特殊的簡化或限制。(因為篇幅原因,這里不做詳細解釋了。)所以以太坊采用了簡單直接的“賬戶模型(account model)”,這與我們已經非常熟悉的大部分中心化軟件系統中所使用的數據模型非常相似。

在以太坊的賬戶模型中,用“地址(address)”來作為賬戶的全局唯一標識,將自定義狀態數據與地址進行綁定來實現快速查找、增刪和修改;這種思路就像我們在傳統的業務系統中所使用的賬戶數據模型那樣,通過唯一的用戶賬戶標識來關聯所有業務數據。這可以說是一種為了實現通用應用平臺而進行的工程上的設計妥協和技術簡化。

在賬戶模型中,每個賬戶都有一個表示其可用“余額(balance)”的字段,來記錄其以太幣(以太坊協議中的代幣)數量。而在比特幣系統中,一個所謂的“賬戶”是可以持有(使用)多個 UTXO 的,我們在客戶端或者錢包中看到的“賬戶余額”實際上是這個賬戶持有的(可以使用的)所有 UTXO 的比特幣數量之和。比特幣中的交易是對可用 UTXO 的合并和拆分,而不是像賬戶模型這樣直接對余額數值進行增減。

以太坊中的“賬戶”,邏輯上分為兩種:EOA(External Owned Account,即由外部用戶基于橢圓曲線數字簽名的私鑰控制的賬戶)和 Contract Account(即合約賬戶)。不過從基礎數據上看,這兩種賬戶是一樣的,它們的區別僅在于賬戶是否與合約代碼相關聯:如果一個賬戶沒有關聯代碼,它就是 EOA;否則它就是合約賬戶。

應該注意到,對于自定義狀態機來講,需要持久化保存的應該是自定義狀態數據和用來修改狀態數據的可執行代碼,這其實就是所謂的“合約狀態”和“合約代碼”。對于智能合約平臺來講,必須能夠持久化地保存這兩種數據。基于賬戶模型,以太坊使用了一個全局的數據結構來保存所有的合約狀態和合約代碼。因為合約是可以由用戶自定義的,所以保存這些數據的數據結構必須是可以進行高效的動態查找、增刪和修改的,并且是可以進行簡單驗證的。以太坊中就使用了一種叫做 Merkle Patricia Tree(簡稱 MPT)的數據結構來實現這一點。

MPT 與比特幣系統使用的 Merkle Tree 類似,也是一種“哈希樹”,所以它們具有相同的特性:任意葉節點數據的變動都會導致根節點哈希的變動,所以根節點哈??梢杂脕順俗R樹中所有數據的某個特定的版本?;谶@個原理,就可以在點對點網絡的參與者之間通過由各個客戶端分別維護的一個全局 MPT 的根節點哈希來驗證所有自定義狀態數據、賬戶余額和代碼數據的版本一致性。這個全局的 MPT 也就是以太坊的“狀態樹(state tree)”,它相當于比特幣系統中所有可用 UTXO 的全集。

以太坊中用來保存所有自定義狀態數據的全局 MPT 被稱為“存儲(storage)”,它是獨立于“狀態樹”之外的另一個全局 MPT,但因為其根節點哈希是作為賬戶數據的一個字段來保存的,所以它實際上也是“狀態樹”的一部分。

以太坊中的每個合約賬戶都可以在“存儲”中使用若干“存儲單元(storage slot)”:每個合約的代碼中可以自定義若干狀態數據,每個狀態數據對應一個或多個“存儲單元”;這些存儲單元都可以通過簡單的尋址算法進行存取操作。這就是以太坊的持久化數據存儲方案。

以太坊中的“狀態轉換”

基于“賬戶模型”和“存儲”,以太坊中的狀態轉換自然也就有了不同的形式。下圖是以太坊中的狀態轉換示意:

以太坊中的狀態轉換

圖中演示了以太坊中的一個由交易引發的狀態轉換:在初始狀態 State 中,14c5f8ba、bb75a980、892bf92f 和 4096ad65 代表了 4 個賬戶地址,其中 14c5f8ba 和 4096ad65 是 EOA,bb75a980 和 892bf92f 則為合約賬戶(因為有關聯代碼)。然后圖中所示的交易,其邏輯意義也很簡單,即從 14c5f8ba 向 bb75a980 發送 10 以太幣,并附加了一些額外的數據 Data,這個 Data 數據的意思是將目標合約的第 2 個“存儲單元”的數值設定為“CHARLIE”。這個交易的執行會產生一個新的狀態 State',其中 14c5f8ba 地址的余額減少了 10 以太幣,bb75a980 地址的余額增加了 10 以太幣,并且 bb75a980 地址的第 2 個“存儲單元”的數值變為了“CHARLIE”。

很明顯,因為基礎數據模型的改動,以太坊中的狀態轉換與比特幣中的狀態轉換幾乎完全不同。與之相應地,構造交易、驗證數據等等的邏輯自然也會完全不同。當然,這里只是一個示意介紹,實際上在以太坊的交易中附加的 data 是一種“可執行代碼”,是可以由用戶自定義的,用戶可以用這些具體的代碼來執行任意的計算任務;這種方式與在比特幣交易的輸入和輸出中附加腳本代碼是類似的。

以太坊中的“可執行代碼”

在以太坊協議中,我們可以在交易的 data 字段中附加一種特殊的“可執行代碼”來完成任意的計算任務,這種“可執行代碼”是在一個虛擬的執行環境中運行的。與比特幣腳本系統的執行環境類似,以太坊的這種虛擬執行環境也是基于“棧(stack)”的;但以太坊的虛擬執行環境還提供了可以供應用程序在運行時使用的臨時存儲空間“內存(memory)”和剛剛介紹過的永久存儲機制“存儲(storage)”。這就使以太坊的虛擬執行環境有了更強的計算能力,更像是一種“虛擬的計算機”,這個虛擬的執行環境就是大名鼎鼎的“以太坊虛擬機(Ethereum Virtual Machine,簡稱 EVM)”,EVM 也是以太坊被稱為“世界計算機(World Computer)”的由來,它也是以太坊與比特幣相比在技術層面的最大創新。

以太坊協議中的這種可以在 EVM 中運行的“可執行代碼”就是所謂的“EVM 字節碼”。EVM 字節碼是以太坊計算能力的根本,這是一種“圖靈完備(Turing-complete)”的操作碼系統。以太坊的高級開發語言 Solidity 就可以編譯為 EVM 字節碼,然后在 EVM 中運行;這種方式與其他編譯型的高級語言是類似的,就像 Java 語言和 Java 虛擬機字節碼的關系那樣。

EVM 字節碼的圖靈完備性,也是其與比特幣的腳本系統相比最大的區別。圖靈完備性標志著 EVM 字節碼可以用來完成任意的計算任務,同時因為 EVM 中還提供了臨時存儲機制和永久存儲機制,這才使以太坊成為了真正的可以完成“通用目的(general propose)”計算任務的“智能合約平臺”。

小結

至此,我想我可以再回答一下“以太坊是什么”這個問題了:以太坊其實就是“區塊鏈”+“以太坊虛擬機”。 就本文的目的而言,你記住這個答案就夠了。

當然,以太坊并不像本文中說的這么簡單,還有許許多多的技術細節等待著你去學習理解,文中所提及的術語大多也可以進行更多的技術解讀。但就像我在引言中說的那樣,本文的目的僅僅是去嘗試解釋一些最基本、最重要的概念,幫助你進入區塊鏈和智能合約的世界。希望你讀完本文之后能有些許收獲。我也要感謝能耐著性子看到這里的朋友!

彩蛋:
本文中的兩個插圖都是從以太坊白皮書中抄來的,細心的你可能會發現:以太坊的狀態轉換示意圖中交易數據的 From 地址寫錯了!是的,你沒看錯,就是寫錯了。如果你發現了這個錯誤,我必須恭喜你,你是個細心人,大概是做技術的人才。而沒有發現的朋友可能需要檢討一下了……。
當然,也請不要多想,我引用這個錯誤的圖片,僅僅是因為我不會 PS,然后還懶,所以這個鍋只能 V 神背了……。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容