java和android如何使用web3j開發(fā)以太坊智能合約并進(jìn)行交易教程

從廣義上講,有web3j支持三種類型的以太坊交易:

  • 1.以太幣從一方交易到另一方
  • 2.創(chuàng)建一個(gè)智能合約
  • 3.與智能合約交易

為了進(jìn)行這些交易吃既,必須有以太幣(以太坊區(qū)塊鏈的代幣)存在于交易發(fā)生的以太坊賬戶中拒秘。這是為了支付gas成本坛芽,這是為支付參與交易的以太坊客戶端的交易執(zhí)行成本留储,支付了這個(gè)成本就能將結(jié)果提交到以太坊區(qū)塊鏈上。獲得以太幣的說明下文會(huì)說到咙轩。

此外获讳,我們還可以查詢智能合約的狀態(tài)。

image

如何獲得以太幣Ether

要想獲得以太幣Ether你有兩種途徑可以選擇:

  • 1.自己開采挖礦
  • 2.從別人那里獲取以太幣

在私有鏈中自己挖礦活喊,或者公共測(cè)試鏈(testnet)是非常簡(jiǎn)單直接的丐膝。但是,在主要的公有鏈(mainnet)中钾菊,它需要很多很明顯的專用GPU時(shí)間帅矗,除非你已經(jīng)擁有多個(gè)專用GPU的礦機(jī),否則基本上不太可行煞烫。如果你希望使用私有鏈浑此,則在這個(gè)官方文檔中有一些指導(dǎo)。

要購(gòu)買以太幣Ether滞详,你需要通過交易所凛俱。由于不同的地區(qū)有不同的交易所,你還需要研究自己去哪兒合適料饥。官方文檔中包含多個(gè)交易所蒲犬,是一個(gè)很好的參考。

以太坊測(cè)試鏈(testnets)

針對(duì)Ethereum以太坊有許多專用測(cè)試網(wǎng)絡(luò)或者叫測(cè)試鏈岸啡,他們由各種客戶端支持原叮。

  • 1.Rinkeby:只支持geth客戶端。
  • 2.Kovan:只支持Parity客戶端巡蘸。
  • 3.Ropsten:支持geth和Parity客戶端奋隶。

對(duì)于開發(fā),建議你使用RinkebyKoVan測(cè)試鏈悦荒。這是因?yàn)樗麄兪褂玫墓ぷ髁孔C明POA共識(shí)機(jī)制达布,確保交易和塊能夠一致并及時(shí)的創(chuàng)建。Ropsten測(cè)試鏈逾冬,雖然最接近公有鏈(Mainnet)黍聂,但是因?yàn)樗褂玫墓ぷ髁孔C明是POW共識(shí)機(jī)制,過去已受到攻擊身腻,對(duì)以太坊開發(fā)人員來說往往有更多的問題产还。

你可以通過Rinkeby測(cè)試鏈的Rinkeby Crypto Fauce請(qǐng)求以太坊幣,具體怎么做可以看這里https://www.rinkeby.io/嘀趟。

有關(guān)如何請(qǐng)求Kovan測(cè)試鏈的細(xì)節(jié)可以在這里找到脐区。

如果你需要在Ropsten上的得到一些以太幣,將你的錢包地址的消息發(fā)布到web3j gitter channel她按,然后會(huì)發(fā)送一些給你牛隅。

在testnet測(cè)試鏈或者私有鏈上挖掘

在ethereum以太坊測(cè)試鏈testnet中炕柔,挖掘難度低于公有鏈mainnet。這意味著你可以用普通的CPU媒佣,比如你的筆記本電腦來挖掘新的以太幣匕累。你需要做的是運(yùn)行一個(gè)以太坊客戶端,例如gethParity默伍,開始做一些儲(chǔ)備欢嘿。進(jìn)一步的資料可在他們的官方網(wǎng)站上獲得。

一旦你開采了一些以太幣也糊,你就可以開始使用以太坊區(qū)塊鏈了炼蹦。

然而,如上所述狸剃,使用Kovan或者Rinkeby測(cè)試網(wǎng)絡(luò)更簡(jiǎn)單些掐隐。

gas

當(dāng)在Ethereum以太坊發(fā)生交易時(shí),必須為執(zhí)行該交易的客戶端支付交易成本钞馁,將該交易的輸出提交到以太坊區(qū)塊鏈Ethereum blockchain虑省。

此成本是通過gas來測(cè)量的,其中g(shù)as是用于在以太坊虛擬機(jī)中執(zhí)行交易指令的數(shù)量指攒。請(qǐng)參閱官方文檔以獲取更多信息慷妙。

當(dāng)你使用以太坊客戶端時(shí)僻焚,這意味著允悦,有兩個(gè)參數(shù)用來指示你希望花費(fèi)多少以太來完成傳輸:

  • gas price :氣體價(jià)格,這是每單位gas中以太的消耗量虑啤。Web3j使用的默認(rèn)價(jià)格為22000000000 wei(22×10-8 Ether)隙弛。這是在交易管理中定義的。
  • gas limit:氣體最大量狞山,這是你愿意在交易執(zhí)行上花費(fèi)的gas的最大總量全闷。單個(gè)交易在一個(gè)以太坊區(qū)塊中有多大的上限,通常將該值限制為小于6700000萍启。當(dāng)前的gas限制在這里查https://ethstats.net/总珠。

這兩個(gè)參數(shù)共同決定了你愿意花費(fèi)在交易成本上的最大量的以太幣Ether。也就是說勘纯,你花費(fèi)的gas不會(huì)超過gas price * gas limit局服。gas價(jià)格也會(huì)影響交易發(fā)生的速度,這取決于其他交易是否能為礦工提供更有利的gas價(jià)格驳遵。

你可能需要調(diào)整這些參數(shù)以確保交易能及時(shí)進(jìn)行淫奔。

交易機(jī)制

當(dāng)你用一些以太幣Ether創(chuàng)建了一個(gè)有效的帳戶時(shí),你可以使用兩種機(jī)制來與以太坊進(jìn)行交易堤结。

  • 通過以太坊ethereum客戶端進(jìn)行認(rèn)證簽名交易
  • 離線交易簽名認(rèn)證

這兩種機(jī)制都是Web3j所支持的唆迁。

通過以太坊ethereum客戶端進(jìn)行認(rèn)證簽名交易

為了通過以太坊客戶端進(jìn)行交易鸭丛,首先需要確保你正在使用的客戶端知道你的錢包地址。最好是運(yùn)行自己的以太坊客戶端唐责,比如geth/Parity鳞溉,以便可以更方便的做到這一點(diǎn)。一旦你有一個(gè)客戶端運(yùn)行妒蔚,你可以創(chuàng)建一個(gè)以太坊錢包穿挨,通過:

  • geth Wiki包含了geth支持的良好運(yùn)行的不同機(jī)制,例如導(dǎo)入私有密鑰文件肴盏,并通過控制臺(tái)創(chuàng)建新的以太坊帳戶科盛。
  • 或者,你可以通過客戶端使用JSON-RPC管理命令菜皂,例如用personal_newAccountgeth/Parity創(chuàng)建新以太坊賬戶贞绵。

通過創(chuàng)建你的錢包文件,你可以通過web3j打開帳戶恍飘,首先創(chuàng)建支持geth/Parity管理命令的web3j實(shí)例:

Admin web3j = Admin.build(new HttpService());

然后榨崩,你可以解鎖帳戶,并如果是成功的章母,就可以發(fā)送一個(gè)交易:

PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount("0x000...", "a password").send();
if (personalUnlockAccount.accountUnlocked()) {
    // send a transaction
}

以這種方式發(fā)送的交易應(yīng)該通過EthSendTransaction創(chuàng)建母蛛,使用Transaction類型:

Transaction transaction = Transaction.createContractTransaction(
              <from address>,
              <nonce>,
              BigInteger.valueOf(<gas price>),  // we use default gas limit
              "0x...<smart contract code to execute>"
      );

      org.web3j.protocol.core.methods.response.EthSendTransaction
              transactionResponse = parity.ethSendTransaction(ethSendTransaction)
              .send();

      String transactionHash = transactionResponse.getTransactionHash();

      // poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt(<txHash>)

其中nonce值獲得方式,下文會(huì)提到乳怎。
有關(guān)此交易工作流的詳細(xì)信息彩郊,請(qǐng)參閱 DeployContractITScenario

web3j支持的各種管理命令的進(jìn)一步細(xì)節(jié)在Management APIs中蚪缀。

離線交易簽名認(rèn)證Offline transaction signing

如果你不想管理自己的以太坊客戶端秫逝,或者不想向以太坊客戶端提供諸如密碼之類的錢包詳細(xì)信息,那么就通過離線交易認(rèn)證簽名询枚。

離線交易簽名認(rèn)證允許你在web3j中使用你的以太坊錢包簽署交易违帆,允許你完全控制你的私有憑據(jù)。然后金蜀,離線創(chuàng)建的交易可以被發(fā)送到網(wǎng)絡(luò)上的任何以太坊客戶端刷后,只要它是一個(gè)有效的交易,它會(huì)將交易傳播到其他節(jié)點(diǎn)渊抄。

如果需要尝胆,還可以執(zhí)行進(jìn)程外交易簽名認(rèn)證。這可以通過重寫ECKeyPairsign方法來實(shí)現(xiàn)抒线。

創(chuàng)建和使用錢包文件Ethereum wallet file

為了離線脫機(jī)交易班巩,你需要有你的錢包文件或與私密錢包/賬戶相關(guān)的公共和私人密鑰。

web3j能夠?yàn)槟闵梢粋€(gè)新的安全的以太坊錢包文件Ethereum wallet file,或者與也可以通過私鑰來和現(xiàn)有的錢包文件一起工作抱慌。

創(chuàng)建新的錢包文件:

String fileName = WalletUtils.generateNewWalletFile(
        "your password",
        new File("/path/to/destination"));

加載憑據(jù)從錢包文件:

Credentials credentials = WalletUtils.loadCredentials(
        "your password",
        "/path/to/walletfile");

然后這些憑據(jù)會(huì)被用來簽署交易逊桦,請(qǐng)參閱Web3安全存儲(chǔ)定義錢包文件規(guī)范Web3 Secret Storage Definition

簽署以太坊交易

要使脫機(jī)簽名交易得到簽署,需要設(shè)定一個(gè)RawTransaction類型抑进。RawTransaction類似于前面提到的Transaction類型强经,但是它不需要通過具體的賬號(hào)地址來請(qǐng)求,因?yàn)榭梢詮暮灻型茢喑鰜怼?/p>

為了創(chuàng)建和簽署原生交易寺渗,交易的順序如下:

  • 1.確定交易發(fā)起者帳戶的下一個(gè)可用隨機(jī)數(shù)nonce
  • 2.創(chuàng)建RawTransaction對(duì)象
  • 3.使用遞歸長(zhǎng)度前綴編碼(RLP即Recursive Length Prefix)對(duì)RawTransaction對(duì)象進(jìn)行編碼
  • 4.簽署RawTransaction對(duì)象
  • 5.將RawTransaction對(duì)象發(fā)送到節(jié)點(diǎn)進(jìn)行處理

nonce是一個(gè)不斷增長(zhǎng)的數(shù)值匿情,用來唯一地標(biāo)識(shí)交易。一個(gè)nonce只能使用一次信殊,直到交易被挖掘完成炬称,可以以相同的隨機(jī)數(shù)發(fā)送交易的多個(gè)版本,但是一旦其中一個(gè)被挖掘完成涡拘,其他后續(xù)提交的都將被拒絕玲躯。

一旦獲得下一個(gè)可用的nonce,該值就可以用來創(chuàng)建transaction對(duì)象:

RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             nonce, <gas price>, <gas limit>, <toAddress>, <value>);

然后可以對(duì)交易進(jìn)行簽名和編碼:

byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, <credentials>);
String hexValue = Numeric.toHexString(signedMessage);

其中憑據(jù)是根據(jù)創(chuàng)建和使用錢包文件加載的鳄乏。

然后使用eth_SendRawTransaction發(fā)送交易:

EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
String transactionHash = ethSendTransaction.getTransactionHash();
// poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt(<txHash>)

有關(guān)創(chuàng)建和發(fā)送原始事務(wù)的完整示例跷车,請(qǐng)參閱 CreateRawTransactionIT

交易隨機(jī)數(shù)nonce

nonce是一個(gè)不斷增長(zhǎng)的數(shù)值橱野,用來唯一地標(biāo)識(shí)交易朽缴。一個(gè)nonce只能使用一次,直到交易被挖掘完成水援,可以以相同的隨機(jī)數(shù)發(fā)送交易的多個(gè)版本密强,但是一旦其中一個(gè)被挖掘完成,其他后續(xù)提交的都將被拒絕裹唆。

可以通過eth_getTransactionCount方法獲得下一個(gè)可用的nonce

EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
             address, DefaultBlockParameterName.LATEST).sendAsync().get();

     BigInteger nonce = ethGetTransactionCount.getTransactionCount();

然后可以使用nonce創(chuàng)建你的交易對(duì)象:

RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             nonce, <gas price>, <gas limit>, <toAddress>, <value>);

交易類型

web3j中的不同類型的交易都使用TransactionRawTransaction對(duì)象誓斥。關(guān)鍵的區(qū)別是交易對(duì)象必須始終有一個(gè)地址只洒,以便處理eth_sendTransaction請(qǐng)求的以太坊客戶端知道要使用哪個(gè)錢包來代表消息發(fā)送者并發(fā)送該交易许帐。如上所述,對(duì)于離線簽名認(rèn)證簽署的原始交易而言毕谴,這不是必須的成畦。

接下來的部分概述了不同交易類型所需的關(guān)鍵交易屬性。下列屬性對(duì)所有人都是不變:

  • Gas price 天然氣氣體價(jià)格
  • Gas limit 天然氣氣體限制
  • Nonce 隨機(jī)數(shù)
  • from 發(fā)送地址

TransactionRawTransaction對(duì)象在所有后續(xù)示例中都可互換使用涝开。

以太幣從一方交易到另一方

在雙方之間發(fā)送以太幣Ether需要交易對(duì)象的最少量的信息:

  • to :目的地錢包地址
  • value:價(jià)值循帐,希望發(fā)送到目的地的以太幣數(shù)量
BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();
RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             <nonce>, <gas price>, <gas limit>, <toAddress>, value);
// send...

但是,建議你使用TransferClass來發(fā)送以太幣Ether舀武,它負(fù)責(zé)對(duì)nonce管理和通過不斷的輪詢?yōu)槟闾峁╉憫?yīng):

Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
TransactionReceipt transactionReceipt = Transfer.sendFunds(
        web3, credentials, "0x<address>|<ensName>",
        BigDecimal.valueOf(1.0), Convert.Unit.ETHER).send();

使用智能合約打包器smart contract wrappers

當(dāng)使用下面列出的智能合約打包器時(shí)拄养,將不得不手動(dòng)執(zhí)行從Solidity到本機(jī)Java類型的所有轉(zhuǎn)換。使用Solidity smart contract wrappers是非常有效的银舱,它負(fù)責(zé)所有的代碼生成和轉(zhuǎn)換瘪匿。

創(chuàng)建一個(gè)智能合約

要部署新的智能合約跛梗,需要提供以下屬性:

  • value :在智能合約中希望存放的以太坊Ether量(如果沒有提供默認(rèn)為零)
  • data :十六進(jìn)制格式化、編譯的智能合約創(chuàng)建代碼
// using a raw transaction
RawTransaction rawTransaction = RawTransaction.createContractTransaction(
        <nonce>,
        <gasPrice>,
        <gasLimit>,
        <value>,
        "0x <compiled smart contract code>");
// send...

// get contract address
EthGetTransactionReceipt transactionReceipt =
             web3j.ethGetTransactionReceipt(transactionHash).send();

if (transactionReceipt.getTransactionReceipt.isPresent()) {
    String contractAddress = transactionReceipt.get().getContractAddress();
} else {
    // try again
}

如果智能合約包含構(gòu)造函數(shù)棋弥,則必須對(duì)關(guān)聯(lián)的構(gòu)造函數(shù)字段值進(jìn)行編碼核偿,并將其附加到編譯的智能合約代碼中compiled smart contract code

String encodedConstructor =
             FunctionEncoder.encodeConstructor(Arrays.asList(new Type(value), ...));

// using a regular transaction
Transaction transaction = Transaction.createContractTransaction(
        <fromAddress>,
        <nonce>,
        <gasPrice>,
        <gasLimit>,
        <value>,
        "0x <compiled smart contract code>" + encodedConstructor);

// send...

與智能合約交易

要與現(xiàn)有的智能合約進(jìn)行交易,需要提供以下屬性:

  • to:智能合同地址
  • value:在智能合約中你希望存放的以太幣Ether量(如果智能合約接受以太幣Ether的話)
  • data: 已編碼的函數(shù)選擇器和自變量參數(shù)

web3j負(fù)責(zé)函數(shù)編碼顽染,有關(guān)實(shí)現(xiàn)的進(jìn)一步細(xì)節(jié)漾岳,請(qǐng)參閱應(yīng)用程序二進(jìn)制接口部分Application Binary Interface

Function function = new Function<>(
             "functionName",  // function we're calling
             Arrays.asList(new Type(value), ...),  // Parameters to pass as Solidity Types
             Arrays.asList(new TypeReference<Type>() {}, ...));

String encodedFunction = FunctionEncoder.encode(function)
Transaction transaction = Transaction.createFunctionCallTransaction(
             <from>, <gasPrice>, <gasLimit>, contractAddress, <funds>, encodedFunction);

org.web3j.protocol.core.methods.response.EthSendTransaction transactionResponse =
             web3j.ethSendTransaction(transaction).sendAsync().get();

String transactionHash = transactionResponse.getTransactionHash();

// wait for response using EthGetTransactionReceipt...

無論消息簽名的返回類型如何,都不可能從事務(wù)性函數(shù)調(diào)用返回值奈梳。但是坝咐,使用過濾器捕獲函數(shù)返回的值是可能的。詳情請(qǐng)參閱過濾器和事件部分耀找。

查詢智能合約狀態(tài)

這種功能是由eth_call通過JSON-RPC調(diào)用來實(shí)現(xiàn)的。

eth_call允許你調(diào)用智能合約上的方法來查詢某個(gè)值业崖。此函數(shù)沒有關(guān)聯(lián)交易成本野芒,這是因?yàn)樗桓淖內(nèi)魏沃悄芎霞s方法的狀態(tài),它只返回它們的值:

Function function = new Function<>(
             "functionName",
             Arrays.asList(new Type(value)),  // Solidity Types in smart contract functions
             Arrays.asList(new TypeReference<Type>() {}, ...));

String encodedFunction = FunctionEncoder.encode(function)
org.web3j.protocol.core.methods.response.EthCall response = web3j.ethCall(
             Transaction.createEthCallTransaction(<from>, contractAddress, encodedFunction),
             DefaultBlockParameterName.LATEST)
             .sendAsync().get();

List<Type> someTypes = FunctionReturnDecoder.decode(
             response.getValue(), function.getOutputParameters());

注意:如果一個(gè)無效的函數(shù)調(diào)用被執(zhí)行双炕,或者得到一個(gè)空null返回結(jié)果時(shí)狞悲,返回值將是一個(gè)Collections.emptyList實(shí)例。

  • web3j教程妇斤,主要是針對(duì)java和android程序員進(jìn)行區(qū)塊鏈以太坊開發(fā)的web3j開發(fā)詳解摇锋。
  • 以太坊教程,主要介紹智能合約與dapp應(yīng)用開發(fā)站超,適合入門荸恕。
  • 以太坊開發(fā),主要是介紹使用node.js死相、mongodb融求、區(qū)塊鏈、ipfs實(shí)現(xiàn)去中心化電商DApp實(shí)戰(zhàn)算撮,適合進(jìn)階生宛。

匯智網(wǎng)原創(chuàng)翻譯,原文訪問這里

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肮柜,一起剝皮案震驚了整個(gè)濱河市陷舅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌审洞,老刑警劉巖莱睁,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡仰剿,警方通過查閱死者的電腦和手機(jī)耙箍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酥馍,“玉大人辩昆,你說我怎么就攤上這事≈继唬” “怎么了汁针?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)砚尽。 經(jīng)常有香客問我施无,道長(zhǎng),這世上最難降的妖魔是什么必孤? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任猾骡,我火速辦了婚禮,結(jié)果婚禮上敷搪,老公的妹妹穿的比我還像新娘兴想。我一直安慰自己,他們只是感情好赡勘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布嫂便。 她就那樣靜靜地躺著,像睡著了一般闸与。 火紅的嫁衣襯著肌膚如雪毙替。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天践樱,我揣著相機(jī)與錄音厂画,去河邊找鬼。 笑死拷邢,一個(gè)胖子當(dāng)著我的面吹牛袱院,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播解孙,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坑填,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼抛人!你這毒婦竟也來了弛姜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤妖枚,失蹤者是張志新(化名)和其女友劉穎廷臼,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荠商,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年寂恬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莱没。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡初肉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饰躲,到底是詐尸還是另有隱情牙咏,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布嘹裂,位于F島的核電站妄壶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寄狼。R本人自食惡果不足惜丁寄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泊愧。 院中可真熱鬧伊磺,春花似錦、人聲如沸删咱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腋腮。三九已至雀彼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間即寡,已是汗流浹背徊哑。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聪富,地道東北人莺丑。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像墩蔓,于是被迫代替她去往敵國(guó)和親梢莽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容