Qtum區塊鏈指南

QTUM量子鏈開發團隊發表於2018-07-16

Qtum區塊鏈指南

Qtum區塊鏈,又稱為量子鏈,是一個基於未花費交易輸出(Unspent Transaction Output,UTXO)和權益證明(Proof of Stake,PoS)的智慧合約平臺,融合了比特幣和以太坊生態系統各自的優點 。智慧合約可以應用在諸多行業,如金融科技,物聯網和身份認證等。智慧合約的核心技術是分散式賬本,也就是我們常常提到的區塊鏈。Qtum區塊鏈實現了完整的智慧合約功能,通過賬戶抽象層(Account Abstraction Layer,AAL)技術把UTXO模型轉換成可供以太坊虛擬機器(Ethereum Virtual Machine,EVM)執行智慧合約的賬戶模型,合約開發者不需關心對合約操作相關的UTXO轉換細節,即可使用EVM的特性進行開發而且相容現有以太坊的智慧合約。

Qtum量子鏈採用了互惠權益證明(Mutualized Proof Of Stake, MPoS)共識機制,使得在智慧合約下實現更安全的PoS共識。另外,獨創性的提出和實現了分散式自治協議(Decentralized Governance Protocol, DGP),DGP是通過內嵌到創世區塊的智慧合約來治理區塊鏈網路的引數,去中心化的網路自治機制使得區塊鏈網路在一定程度上實現自動升級和快速迭代而無需進行軟體升級。

本指南介紹Qtum區塊鏈基本概念和使用的技術,介紹了Qtum的交易型別和智慧合約的使用,對Qtum區塊鏈的使用可以有一個基本的瞭解。

Qtum區塊鏈簡介

首先介紹一下區塊鏈相關的概念。

區塊鏈基本概念

區塊鏈是一種去中心化、分散式的賬本,賬本以冗餘的方式儲存在所有參與節點。區塊鏈主要由以下底層技術組成:密碼學、共識演算法、點對點網路。就資料組織方式來看區塊鏈是由一系列的區塊連結形成的一種資料結構。最底層的第一個區塊是創世區塊,隨後每個新區塊都被放置在前一個區塊之上,這些區塊有序地連結在一起形成鏈。區塊之間是通過雜湊指標進行連線的,雜湊指標表示從原區塊指向目標區塊並且在目標區塊儲存有原區塊的雜湊值。區塊由區塊頭和區塊記錄組成,區塊頭用於描述本區塊的組成資訊,區塊頭最重要的用途是用作記錄前一區塊頭雜湊值和區塊記錄的根雜湊值。

簡化版區塊鏈示意圖

一個或多個新的交易收集到一起成為了一個區塊的交易資料,這些資料作為區塊記錄。為了對資料完整性進行保護,每個交易的副本都會進行SHA256雜湊,然後這些雜湊作為Merkle 樹的節點,對Merkle樹節點進行從下到上的雜湊運算,最終在 Merkle根節點得到一個根雜湊值。該雜湊寫入到區塊頭,而區塊頭也進行雜湊運算得到一個雜湊值,該雜湊值寫入下一個區塊頭部,因此通過寫入區塊頭的根雜湊值就可以驗證區塊記錄。

由於區塊頭裡的雜湊值與前一個區塊相關,如果前一個區塊內容發生變化,其雜湊值也會發生變化,因此會改變當前區塊的雜湊值,這個改變會傳導到下一個區塊,並再傳導到下下一個區塊,以此類推,直到最後一個區塊。因此當改變某個區塊記錄時,會破壞該區塊之後的連結關係,除非對該區塊之後所有區塊進行相應的更改,即重新計算符合共識的雜湊值。共識演算法是用來確保重新計算雜湊值在一個合適的難度,這樣如果想改變區塊內容,必須在計算能力或權益大小上超過共識難度,多個區塊共識難度的不斷積累,使得在概率上保證了最長鏈的安全性,這是就是工作量證明(Proof of Work,PoW)和權益證明(PoS)共識演算法的作用原理。比特幣區塊鏈通過工作量證明,而Qtum區塊鏈採用的是權益證明機制改進演算法:互惠權益證明(MPoS)。

點對點網路是實現Qtum節點之間進行通訊的方法,交易廣播、區塊同步與廣播等都通過點對點網路來實現。通過點對點網路,每個節點共享同一份的賬本,並對賬本進行驗證,共識演算法和共識規則是進行驗證的標準,由於共識的一致,和密碼學結合確保了作惡節點無法篡改和作假賬本上的資料。可以看到,密碼學、共識演算法和點對點網路的結合確保了區塊鏈在去中心化的條件下能實現可信的賬本。Qtum在此基礎上增加了可以執行智慧合約虛擬機器,從而實現了一個高度智慧化的價值傳輸網路。

Qtum區塊頭

Qtum量子鏈的區塊頭描述了區塊的狀態記錄,用於管理記錄區塊交易結果相關的資訊和共識演算法所需的資料。以下是Qtum區塊頭資料結構的定義:

Qtum區塊頭

其中nVersion版本資訊描述了當前Qtum區塊鏈軟體的版本,hashPrevBlock記錄前一區塊頭雜湊值,hashMerkleRoot記錄本區塊交易ID生成的Merkle樹根節點雜湊值,nTime記錄區塊產生的時間,nBit記錄當前計算區塊頭雜湊值的難度,nNonce與比特幣相容,但PoS階段未使用,hashStateRoot記錄本區塊EVM執行完成後的根狀態雜湊值,hashUTXORoot記錄本區塊EVM執行完後產生的UTXO根狀態雜湊值,prevoutStake為前一區塊用於PoS過程的交易輸出點,vchBlockSig是PoS時使用的區塊簽名。

Qtum區塊

Qtum交易的基本單位是未花費的一個交易輸出,簡稱UTXO。UTXO是不能再分割,並記錄在區塊鏈中。一個交易的輸入是一個或多個UTXO,生成交易時對這些UTXO進行簽名用於解鎖輸入,簽名標誌著對某個地址上Qtum的使用許可。這些簽名後的交易廣播到Qtum網路中。網路的每一個全節點都可以接收、驗證、和在網路中轉發這些交易。Qtum區塊鏈每隔一段時間就有挖礦節點產生新的區塊,把驗證通過的交易記錄到區塊。

Merkle樹是一種雜湊二叉樹,用於快速歸納和校驗大規模資料完整性。這種二叉樹的節點包含雜湊值。在Qtum區塊鏈中,Merkle樹用來組織每個區塊中的交易標識(txid)。txid是對交易進行兩次雜湊演算法生成。Merkle樹是自底向上構建的,通過對相鄰葉子節點的 txid 配對然後做雜湊運算,生成為父節點,對所有葉子節點重複這個過程,並對生成的父節點進行類似的操作,只到剩下頂部的一個節點,最終構建了 merkle 樹。如下圖所示:

Merkle樹

在簡化支付驗證(SPV)提案中指出,Merkle 樹允許客戶端通過一個完整節點從一個區塊頭中獲取其 Merkle 根節點和中間雜湊值列表來驗證一個交易被包含在這個區塊中。這個完整節點並不需要是可信的,因為偽造區塊頭十分困難而中間雜湊值是不可能被偽造的,否則驗證就會失敗。

Qtum的PoS區塊至少包含2筆交易。這些交易的第一筆是一個特殊的 coinbase 交易,該交易沒有Qtum輸出。第二筆交易是coin stake交易,它包含了這個區塊所有交易費和區塊獎勵。coin stake交易在之後的 500 個區塊內之後才能花費,在Qt錢包上顯示staking的Qtum就是參stake之後不夠500 個區塊鎖定的。

MPoS共識演算法

Qtum基本的共識演算法基於PoSv3共識機制。關於共識機制孰優孰劣的討論一直在進行中,最常被討論的共識機制有:工作量證明機制PoW 、權益共識機制PoS 、動態權益共識機制和HyperLedger的拜占庭容錯機制 。共識機制的目的是利用分散式演算法達成資料的一致性。正如Fischer Lynch & Paterson定理指出,除非所有節點達成100%一致,否則無法達成共識。 在比特幣網路中,礦工通過工作量證明機制雜湊碰撞參與交易驗證。當礦工計算出滿足一定條件的雜湊值時,礦工可以向全網宣佈新區塊的誕生:

Hash(BlockHeader) ≤ M/D

M是礦工數量,D是挖礦難度,Hash()代表SHA256雜湊運算,輸出值範圍為[0,M]。比特幣的SHA-256雜湊運算滿足快速驗證(方便網路中每個節點對運算結果進行驗證)、可調整的難度值(可以根據全網算力進行調整)和相對公平性(也就是說,每個礦工解決雜湊計算的概率與其算力成正比)。 在PoSv3交易中,新區塊的產生必須滿足下列條件:

ProofHash < coins × target

在ProofHash中,StakeModifier 利用未花費輸出和當前時間進行運算。由於Qtum實現了智慧合約,交易處理需要花更多的時間去和智慧合約互動和執行,因此需要更動態的費用機制。這其中有影響Qtum的幾個安全隱患。一個比較大的隱患是,攻擊者可以通過支付昂貴費用執行惡意程式,但由於這些費用會歸於區塊生產者,最終攻擊者付出的費用會變得很小。基於現有PoS系統的加密貨幣由於不支援圖靈完備的智慧合約VM,不會受到這類攻擊的影響。Qtum是第一個基於PoS和以太坊智合約的區塊鏈,實現了規範在區塊鏈上允許的計算用途和能力的gas機制。

Qtum進一步對PoSv3做了一個修改,用於部分解決通過垃圾交易攻擊而產生的無用satke問題。採用PoSv3一致的共識機制,但改變了區塊獎勵和交易費用的支付體系。與區塊生產者會立即收到區塊獎勵和交易費用相比,新的方法是獎勵和交易費用在網路中多個挖礦者之間互相共享。具體說來,區塊生產者在生成區塊的時候會收到總費用的1/10,而經過預定的區塊確認時間之後,可以接收到另外9個塊的費用的1/10。

這個新的方法看起來改動很微小,但它解決了影響Qtum的幾個安全隱患。一個比較大的隱患是,攻擊者可以通過買入足夠的幣從而成為有可能的區塊生產者,通過某些EVM操作碼使網路變得容易遭受DoS攻擊。這隻需要很小的代價,甚至惡意交易需要消耗交易費用和gas,攻擊者可以通過支付昂貴費用執行惡意程式,但由於這些費用會歸於區塊生產者,最終攻擊者付出的費用會變得很小。使用MPoS,就不會出現這種情況,產生區塊是隻能收到1/10的gas費用,除非他能再挖出連續的9個區塊,否則其餘9/10的gas費用會因分給網路上其他的挖礦者而丟失。因此會導致這種型別的垃圾交易攻擊會變得很昂貴。

當一個區塊產生時,區塊生產者的獎勵交易必須包含至少10個輸出。第一個輸出屬於本區塊生產者,可以接收自己用於stake的幣和1/10的交易費用,其他九個輸出屬於500個區塊之前的區塊生產者。當一個區塊產生時,增加一個獎勵費用的接收者,同時減去另外一個接收者,因此總接收者數量一直有10個。區塊生產者另外9/10的獎勵將在500個區塊之後,即(+501,+502,...,+509)每個區塊獎勵的1/10。

AAL和智慧合約

智慧合約(Smart Contract),以程式設計方式定義的一系列承諾,包括合約參與方可以在上面執行這些承諾的協議。通過區塊鏈可以實現這種智慧合約的程式設計,並在區塊鏈上執行,因此一旦設立指定後,能夠無需中介的參與自動執行。

Qtum實現了滿足以太坊虛擬機器(EVM)規範的智慧合約功能,在Qtum上可以部署和呼叫智慧合約。以太坊虛擬機器使用了256位元長度的機器碼,是一種基於堆疊的虛擬機器,用於執行以太坊智慧合約。由於EVM是針對以太坊體系設計的,因此使用了以太坊賬戶模型(Account Model)進行價值傳輸。而Qtum量子鏈的設計是基於比特幣UTXO模型,所以在量子鏈模型設計中加入了賬戶抽象層(Account Abstraction Layer),用於將UTXO模型轉換成可供EVM執行的賬戶模型。賬戶抽象層可以隱藏某些特定功能部署細節,併為增強互操作性和平臺獨立性建立關注劃分。

Qtum量子鏈中的所有交易使用比特幣指令碼語言,並在其基礎上進行了擴充,加入了三個全新的操作符。

  • OP_CREATE – 用於執行EVM智慧合約的建立,把通過交易傳輸的位元組程式碼存放到合約RLP資料庫,並生成一個合約賬號;
  • OP_CALL – 用於傳遞呼叫智慧合約所需要的相關資料(即EVM中的CALLERDATA)和地址資訊,並執行合約中的程式碼內容。該操作符還可為智慧合約傳送資金。
  • OP_SPEND – 將當前合約的ID雜湊值作為輸入的交易HASH,或傳送到合約的UTXO的交易HASH,然後使用OP_SPEND作為花費指令構建交易指令碼。

在比特幣系統中,只有當解鎖指令碼(ScriptSig)與鎖定指令碼(ScriptPubKey)驗證通過後才能花費相對應的交易輸出。舉例來說,鎖定指令碼通常會把一個交易輸出鎖定到一個比特幣地址上(公鑰的雜湊值),只有當解鎖指令碼和鎖定指令碼的設定條件相符時,執行組合指令碼才會顯示結果為真(系統返回值為1),這樣相對應的交易輸出才會被花費。

而在Qtum系統中,我們更強調智慧合約執行的及時性。因此我們在鎖定指令碼中加入了OP_CREATE和OP_CALL操作符。當Qtum系統檢測到該操作符時,全網節點就會執行該交易。這樣一來,比特幣指令碼扮演的角色,更多的是將相關資料傳送至EVM,而不僅僅作為一種編碼語言。與以太坊執行智慧合約一樣,由OP_CREATE和OP_CALL操作符觸發的合約,EVM會在各自的狀態資料庫中更改其狀態。

考慮到量子鏈智慧合約的易用性,需要對觸發智慧合約的資料以及資料來源的公鑰雜湊值進行驗證。為了防止量子鏈上UTXO所佔比例過大,將OP_CREATE和OP_CALL的交易輸出也設計成可花費的,OP_CALL的輸出可以為其他合約或公鑰雜湊地址傳送資金。

對於智慧合約的開發者來說,EVM的賬戶模型相對簡單。它支援合約餘額的查詢,還可為其他合約傳送資金等操作。對於在Qtum上建立的智慧合約,系統會生成一個交易雜湊值用於合約的呼叫。新合約的初始餘額為0(目前不支援非0初始餘額的合約)。為了滿足合約傳送資金的需求,Qtum使用OP_CALL操作符來建立交易輸出。

目前Qtum支援使用Solidity語言進行編寫的智慧合約,並且使用比如Remix Solidity IDE進行開發和編譯智慧合約。部署智慧合約或和合約進行互動可以通過Qtum提供的RPC呼叫或PC錢包進行。

分散式自治協議

Qtum區塊鏈的分散式自治協議(Decentralized Governance Protocol,DGP)是通過智慧合約實現的,可管理的每個區塊鏈網路功能都由獨立的DGP智慧合約(採用DGP-template描述)控制,這意味著每個功能有獨立的治理、授權機制以及內建限制條件。每個DGP都有一個非常簡單的核心治理模式:即通過具有管理或治理席位的地址來對提案進行管理,包括對投票席位本身和普通提案的管理。現在支援0,1,2三種型別的提案,分別對應:管理或治理席位增加、管理或治理席位刪除、普通引數提修改。所有提案的設定只有具備管理席位的傳送地址才有許可權設定,具有管理或投票席位的傳送地址才能進行投票。

對2型別提案,即普通型別提案的投票,至少支援以下專案:

  • 每個Qtum虛擬機器操作碼對應的Gas價格
  • 區塊建立者可接受的交易對應最低Gas價格
  • 區塊大小
  • 區塊gas限制

具體的網路引數更改流程為:

  • 設計DGP引數更改提案。提案中需要明確新的引數值、實施變更的起始區塊以及投票過程所對應的區塊數量。
  • 向社群公佈更改提案,並收集相關反饋;
  • 根據社群反饋,對更改提案進行相應調整;
  • 將最終版提案傳送至DGP智慧合約;
  • 投票立即啟動;
  • 具有管理或治理席位的代理者可以傳送一筆交易給DGP智慧合約,對該提案進行投票;
  • 在投票過程中,若提案未獲得足夠投票,則該提案被否決,不執行任何修改;
  • 若提案得到足夠同意票,則DGP分散式自治合約將提案中的相關資料儲存在持久RLP特殊儲存空間內;

提案投票成功後會更新到相應的變數儲存,新引數會在500個塊之後生效,以避免出現不必要的孤兒塊或分叉,錢包和區塊鏈上的所有節點可以定時檢查RLP儲存從而判斷是否有新的更改發生。對於0,1型別的提案,即管理或治理席位增加和刪除,其投票流程和普通提案類似,也是通過具有管理或治理席位的傳送者投票來決定,不過當投票通過後席位的變化可以立即生效。

交易

Qtum區塊鏈支援比特幣型別交易,即UTXO型別的交易,目前支援比特幣定義的五種UTXO型別的交易。UTXO交易的基本單位是未經使用的一個交易輸出,當接收比特幣時,金額是在輸出的UTXO裡的,並且通過指令碼來鎖定,要花費這個UTXO需要提供解鎖指令碼。對於智慧合約功能,當需要進行部署合約或呼叫合約相關功能時,是通過合約交易來觸發的,合約交易的形式很像UTXO,是通過增加了操作碼進行擴充套件的。

UTXO賬戶模型

在未花費交易輸出(UTXO)模型中,交易使用未花費的比特幣作為輸入,此時輸入的UTXO就會作廢,而輸出是另一個UTXO, Qtum數量上變化的結果會在新的UTXO記錄。一定數量的Qtum在不同私鑰持有人之間進行轉移,新的未花費交易輸出在交易中花費,並記錄在區塊上。在交易中,UTXO可用交易接收方公鑰地址生成的祕鑰進行解鎖。Qtum處理交易時利用指令碼語言只能進行有限的操作,並以堆疊的形式進行資料處理 ,並遵循“後進先出”(FIFO)原則。

基於UTXO模型的交易

UTXO模型有諸多優勢: 任何人可以通過比特幣公共賬本對每一筆交易歷史進行查詢,UTXO有良好的可擴充性,能夠同時處理多個地址發起的交易請求。此外,UTXO模型也提供了隱私保護,使用者可以使用變更地址作為UTXO輸出。

每一筆UTXO交易都會記錄在區塊賬本上,只要知道了私鑰就可以掃描賬本獲得所有屬於該私鑰使用者的UTXO。使用者的所有餘額,是所有屬於使用者私鑰的UTXO金額的總和,錢包通過掃描整個區塊鏈收集到使用者所有的UTXO來計算該使用者的餘額。

合約賬戶模型

比特幣指令碼語言並不是圖靈完備的,無法實現迴圈功能。這極大地制約了交易執行量和交易複雜度。因此Qtum量子鏈在UTXO模型的基礎上加入抽象賬戶層設計,在基於UTXO模型的交易上實現智慧合約平臺。

Qtum合約賬戶

Qtum量子鏈智慧合約功能使用了以太坊虛擬機器(EVM),EVM使用了與UTXO不同的賬戶模型,EVM使用基於賬戶(Account)的模型。 具體來說,以太坊通過賬戶狀態的改變進行價值和資訊的交換與傳輸,並通過長度為20位元組的隨機數作為指標以確保交易處理的唯一性。用於供內部使用的費用是以Qtum計價,通過合約交易中的引數GasPrice和GasLimit來指定。對於以太坊EVM合約程式碼是可選的,但對Qtum的合約賬號來說是強制的,即賬號的生成必定伴隨有合約程式碼,生成賬號時儲存預設為空。

以太坊賬戶有兩種型別,一種由外部私鑰控制的外部賬戶,另一種由合約程式碼控制的合約賬戶。外部賬戶用於資訊傳輸的建立、交易簽名。合約賬戶用於收到內部儲存讀寫操作資訊後建立合約或傳送其他資訊。以太坊中的賬戶餘額管理與日常生活中的銀行賬戶管理相類似。每一個新產生的區塊都有可能影響其他賬戶的全域性狀態。每個賬戶都有各自的餘額、儲存和程式碼空間用於呼叫其他賬戶或地址。Qtum智慧合約賬戶和以太坊一致,通過長度為20位元組的隨機數作為地址,但沒有外部私鑰控制的外部賬戶,UTXO賬戶和以太坊的外部賬戶類似,但通過指令碼語言,其功能比以太坊強大。

交易型別

分為普通交易和合約交易兩種交易型別。

普通交易

Qtum區塊鏈的普通交易和比特幣的交易是相容的,目前支援比特幣定義的五種UTXO型別的交易,分別為:P2PKH(Pay to Public Key Hash)、P2PK (Pay to Public Key)、多重簽名(少於15個私鑰簽名)、P2SH (Pay to Script Hash)和OP_RETURN。利用這五種交易標準,客戶端可以滿足複雜的支付邏輯。以下舉例簡單說明各種交易型別的用法:

P2PKH交易

使用P2PKH交易方式,我們假設使用者向虛擬Qtum地址Bread Address支付了0.01 QTUM購買麵包。該交易的輸出為:

OP_DUP OP_HASH160 <Bread Public Key Hash> OP_EQUAL OP_CHECKSIG

OP_DUP複製堆疊頂層資料;OP_HASH160返回公鑰雜湊值並存入棧頂。除了公鑰雜湊值,還需要數字簽名和數字祕鑰才能擁有QTUM所有權。若棧頂資料一致,則OP_EQUAL返回真值(1),否則返回非真值(0)。OP_CHECKSIG生成公鑰和簽名,並校驗交易雜湊值。若一致,則返回真值。

鎖定指令碼相對應的解鎖指令碼為:

<Bread Signature> <Bread Public Key>

將上述兩個指令碼相結合:

<Bread Signature> <Bread Public Key> OP_DUP OP_HASH160 <Bread Public Key Hash> OP_EQUAL OP_CHECKSIG

只有當解鎖指令碼和鎖定指令碼滿足預先設定的條件時,執行結合指令碼的輸出為真。上述例子中,當Bread Signature簽名與Bread Address私鑰相匹配,則返回真值。

P2PK交易

P2PK交易的鎖定指令碼為:

<Bread Public Key> OP_CHECKSIG

對應的解鎖指令碼為:

<Bread Signature>

將上述兩個指令碼相結合:

<Bread Signature> <Bread Public Key> OP_CHECKSIG

這樣只要Bread Signature使用Bread Public Key對應的私鑰簽名,執行結合指令碼的輸出為真。

多重簽名交易

一個M-N型別的多重簽名交易的鎖定指令碼為:

M <Public Key 1> <Public Key 2> ... <Public Key N> N OP_CHECKMULTISIG

鎖定指令碼需要至少M個簽名才能解鎖。

一個設定了K(K>=M)個簽名的解鎖基本為:

OP_0 <Signature 1> <Signature 2>…<Signature K>

將上述兩個指令碼相結合:

OP_0 <Signature 1> <Signature 2>…<Signature K> M <Public Key 1> <Public Key 2> ... <Public Key N> N OP_CHECKMULTISIG

通過執行這個組合指令碼,只要簽名成功的個數達到M就會輸出真。

P2SH交易

P2SH交易的鎖定指令碼為:

OP_HASH160 <redeem scriptHash> OP_EQUAL

其中redeem scriptHash是解鎖指令碼的雜湊值。

解鎖指令碼的形式為: <Signature> {redeem script}

P2SH執行等效於以下的兩個驗證:

1) {redeem script} OP_HASH160 <redeem scriptHash> OP_EQUAL 2)<Signature> {redeem script}

首先1)用於驗證{ redeem script }為是否真,2)再驗證redeem script的執行結果為真,只有兩個驗證都為真時,整個贖回指令碼才輸出真。

OP_RETURN

OP_RETURN允許在交易輸出上增加40位元組的非交易資料,一般這個資料是一個雜湊值,用於記錄證明。OP_RETURN 輸出的資金不能被使用,所以設定為一個金額為0的輸出,任何輸出不為0的QTUM都會消失而不可用。OP_RETURN交易格式很簡單,如下所示:

OP_RETURN <data>

一個P2PKH交易例子

下面使用P2PKH交易方式,使用sendtoaddress傳送一筆交易到一個公鑰雜湊地址,詳細的交易資訊如下:

{
  "txid": "41af815df6af399bec82b4e7b25587463aec6c2c6a11815ddd62aaa314b9aa0c",
  "hash": "41af815df6af399bec82b4e7b25587463aec6c2c6a11815ddd62aaa314b9aa0c",
  "size": 225,
  "vsize": 225,
  "version": 2,
  "locktime": 720,
  "vin": [
    {
      "txid": "2dac9840b183661e5aed458133daa466765131bed7b2cd4e625ef9d477c81b71",
      "vout": 0,
      "scriptSig": {
        "asm": "3044022073caa7d8fe0ba4a7561a6165369c32d6de48d594f0eab169aee82c915205ecc6022050c9ee0dcc7e8a967ea64e8c40df271c479d8bed446e10d0b4da9e05352248bc[ALL] 02646b87a66a70311619fe6e1cc0300a6940fd5bc191c16f1d6d4d1cea9fbe8e74",
        "hex": "473044022073caa7d8fe0ba4a7561a6165369c32d6de48d594f0eab169aee82c915205ecc6022050c9ee0dcc7e8a967ea64e8c40df271c479d8bed446e10d0b4da9e05352248bc012102646b87a66a70311619fe6e1cc0300a6940fd5bc191c16f1d6d4d1cea9fbe8e74"
      },
      "sequence": 4294967294
    }
  ],
  "vout": [
    {
      "value": 12.50000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 52f60b28f652ff43e07ddae02e6bb037f6937ef8 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a91452f60b28f652ff43e07ddae02e6bb037f6937ef888ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "qR83KAp8u2nCxSpwTx39MSTrFedMerJydA"
        ]
      }
    }, 
    {
      "value": 1987.49909600,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 0bb60c781c8f31be21e3901b63cb7f25dd3aeeb0 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a9140bb60c781c8f31be21e3901b63cb7f25dd3aeeb088ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "qJdJg7BaPV89Em8xQZyMdHni4Ss3VG5fTo"
        ]
      }
    }
  ]
}
複製程式碼

其中輸入UTXO的hex格式的解鎖指令碼由以下組成:

使用私鑰進行簽名的結果:473044022073caa7d8fe0ba4a7561a6165369c32d6de48d594f0eab169aee82c915205ecc6022050c9ee0dcc7e8a967ea64e8c40df271c479d8bed446e10d0b4da9e05352248bc0121
複製程式碼
對應的公鑰:
02646b87a66a70311619fe6e1cc0300a6940fd5bc191c16f1d6d4d1cea9fbe8e74
複製程式碼

組合在一起就是"scriptSig"裡面的內容了。輸出的UTXO 0鎖定指令碼為:

OP_DUP OP_HASH160 52f60b28f652ff43e07ddae02e6bb037f6937ef8 OP_EQUALVERIFY OP_CHECKSIG
複製程式碼

合約交易

Qtum在設計上以比特幣UTXO為基礎賬戶模型實現了支援EVM規範的智慧合約,這是通過新增UTXO操作碼和賬戶抽象層(AAL)來完成的。AAL對UTXO賬戶和EVM合約賬戶之間進行了適配,這樣通過AAL可以使用UTXO交易輸出實現在鏈上建立智慧合約,傳送交易到合約賬戶用於觸發合約的執行,完成執行後AAL最終對執行結果進行處理並適配至UTXO。由於採用了AAL,合約開發者不需關心對合約操作相關的UTXO轉換細節,即可使用EVM的特性進行開發而且相容現有以太坊的智慧合約。

Qtum合約交易處理

Qtum 針對UTXO交易指令碼新增了三個操作碼OP_CREATE,OP_CALL和OP_SPEND,目的是用於為UTXO和EVM賬戶模型之間的轉換提供操作支援。這個三個操作碼分別有以下作用:OP_CREATE用於智慧合約的建立;OP_CALL用於合約的執行;OP_SPEND用於合約餘額的花費。

產生或驗證新的區塊時,除了對UTXO交易進行常規的引數合法性、共識規則、DDOS攻擊檢查等之外,還需要使用操作碼檢查函式判斷交易輸出是否包含OP_CREATE或OP_CALL,分別對應著EVM需要執行合約建立或合約呼叫。在合約建立和執行前,需要進行UTXO交易到EVM模型交易的轉換,之後使用構建的EVM執行環境和引擎,完成合約的執行。

目前合約交易相關的qtum-cli命令或RPC有:

  • 合約部署: createcontract,該命令將智慧合約部署到量子鏈上,格式如下
createcontract "bytecode" (gaslimit gasprice "senderaddress" broadcast)
複製程式碼

其中: bytecode(必選): 智慧合約編譯生成的位元組碼 gaslimit(可選): 最大gas數量,預設是2500000 gasprice(可選):gas價格,以QTUM為單位,預設為0.0000004 senderaddress(可選):指定傳送者的地址,預設為當前賬號地址 broadcast(可選):是否廣播,預設為true

比如,

qtum-cli createcontract  "60606040525b33600060006101000a81548173fffffffffffffffffffffffffffff
fffffffffff02191690836c010000000000000000000000009081020402179055506103786001600050819055505b600c80605b6000396000f360606040526008565b600256"
複製程式碼

qtum-cli createcontract   "60606040525b33600060006101000a81548173ffffffffffffffffffffffffffff
ffffffffffff02191690836c010000000000000000000000009081020402179055506103786001600050819055505b600c80605b6000396000f360606040526008565b600256" 3000000 0.0000005
複製程式碼

都可以完成部署同一個智慧合約。

  • 合約交易:sendtocontract,該命令將傳送資料到智慧合約,即呼叫智慧合約相關函式。
sendtocontract "contractaddress" "data" (amount gaslimit gasprice senderaddress)
複製程式碼

contractaddress (必選): 智慧合約地址,大小20位元組 data(必選): 智慧合約呼叫函式及引數 amount:傳送到智慧合約的QTUM數量,可選擇為0 gaslimit(可選): 最大gas數量,預設是2500000 gasprice(可選):gas價格,以QTUM為單位,預設為0.0000004 senderaddress(可選):指定傳送者的地址,預設為當前賬號地址 broadcast(可選):是否廣播,預設為true

比如,

qtum-cli sendtocontract "c6ca2697719d00446d4ea51f6fac8fd1e9310214" "54f6127f"
複製程式碼

qtum-cli sendtocontract "c6ca2697719d00446d4ea51f6fac8fd1e9310214" "54f6127f" 12.0015 6000000 0.0000005
複製程式碼

qtum-cli sendtocontract "c6ca2697719d00446d4ea51f6fac8fd1e9310214" "54f6127f" 12.0015 6000000 0.0000005 qYcH9wHcd86LaDAAxquKPyfpmSraxAbBop
複製程式碼

都可以完成傳送交易到智慧合約,呼叫智慧合約提供的功能。當需要配置某個引數時,該引數前面的引數也要配置,比如需要配置senderaddress時,gaslimit和gasprice也要相應的配置。

Qtum全節點和錢包

Qtum主網釋出後在連結 github.com/qtumproject…上提供已經編譯好的軟體下載,支援Windows 、Linux和OSX平臺,支援X86和ARM架構。也可以自己 下載原始碼進行編譯生成。Qtum core可執行軟體qtumd和qtum-qt都具有全節點功能,同時也具有錢包功能。 節點資料和錢包檔案wallet.dat預設儲存在電腦的特定目錄下,不同作業系統對應的目錄如下:

  • Linux: ~/.qtum
  • Mac OSX: ~/Library/Application Support/Qtum
  • Windows: %APPDATA%\Qtum

下面介紹在Linux上和Mac OS上從原始碼編譯Qtum Core的方法。

Ubuntu16.04上安裝Qtum

安裝依賴

sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils git cmake libboost-all-dev
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:bitcoin/bitcoin
sudo apt-get update
sudo apt-get install libdb4.8-dev libdb4.8++-dev
sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
複製程式碼

拉取Qtum原始碼

git clone --recursive https://github.com/qtumproject/qtum.git
cd qtum
git submodule update --init --recursive
複製程式碼

編譯程式

cd 到qtum目錄下,執行

./autogen.sh
./configure 
make install
複製程式碼

此時src資料夾會生成qtumd、qtum-cli、qtum-tx,和src/qt資料夾下的qtum-qt

Mac OS上安裝Qtum

環境準備

以下需要安裝的工具或者庫,如果已經安裝過,可以忽略對應步驟,直接進入下一步。

  • 安裝Homebrew
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    複製程式碼
  • 安裝命令列工具
    xcode-select --install
    複製程式碼
  • 安裝依賴
    brew install cmake automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf qt libevent
    複製程式碼

這一步安裝的包比較多,如果電腦裡從未安裝過以上的包的話,需要耐心的等待一段時間。

拉取Qtum程式碼

首先找個路徑來存放qtum的程式碼,沒有的話新建個路徑,比如程式碼放在路徑~/workspace/qtum

cd ~/workspace/ qtum
git clone --recursive https://github.com/qtumproject/qtum.git
cd qtum
git submodule update --init –recursive
複製程式碼

編譯程式碼

./autogen.sh
./configure
make install
複製程式碼

此時src資料夾會生成qtumd、qtum-cli、qtum-tx,和src/qt資料夾下的qtum-qt

Qtum錢包

QTUM的所有權是私鑰、地址和簽名來確立的。私鑰是QTUM的所有權的證明,所有權認證基於密碼學證明的安全模型。私鑰的洩漏也就會導致得到私鑰的人可以轉移掉私鑰控制的QTUM,因此要保護好自己的QTUM私鑰。地址是由私鑰匯出公鑰,並對公鑰進行雜湊和編碼後得到的,用於接收QTUM。簽名用私鑰對交易進行簽名並形成解鎖指令碼,從而證明某個UTXO的所有權。錢包,是管理生成、儲存私鑰,並實現接收和傳送QTUM功能的工具,錢包一般把私鑰儲存在一個檔案或簡單的資料庫中,因此錢包檔案的儲存很重要,在沒備份私鑰的情況下丟失錢包檔案也就丟失了該私鑰擁有的QTUM。下面介紹兩種QTUM錢包的使用。

qtumd自帶錢包

Qtumd自帶錢包資料儲存在.qtum目錄下的wallet.dat檔案,所以要妥善保管wallect.dat檔案,需要經常進行備份否則一旦丟失或損壞裡面的QTUM將永久丟失。qtum-cli是和qtumd互動的命令列工具,通過qtum-cli + 命令 + 引數方式使用。

錢包相關的常用命令有:

getaccount "address"       // 獲取地址對應的賬戶名
getaccountaddress "account"   // 獲取某個賬戶名下關聯的一個地址
getaddressesbyaccount "account"  // 獲取某個賬戶名下關聯的所有地址
getbalance ( "account")  // 獲取賬戶可花費的QTUM數量
getnewaddress ( "account" ) //生成指定賬戶名的一個新地址
dumpprivkey "address"      //匯出私鑰
importprivkey  "mykey" // 匯入私鑰
listaccounts //列出所有在用賬戶名
sendtoaddress "address" amount //往某個地址傳送一定數量的QTUM
複製程式碼

PC錢包

qtum-qt錢包支援完整功能的全節點,支援錢包應用。PC錢包資料儲存在.qtum目錄下的wallet.dat檔案,和qtumd共享這個檔案,要妥善保管wallect.dat檔案,經常進行備份。執行qtum-qt即可以開啟軟體。開啟錢包時進入到Overview介面,如下所示:

往特定的地址傳送Qtum

點選錢包左邊的Send按鈕,進入傳送Qtum的操作介面,可以往特定的地址傳送Qtum。使用流程如下:

  1. 在Pay to輸入框輸入接收Qtum的地址
  2. Amount輸入框輸入要傳送的Qtum數量
  3. 點選Choose可以選擇交易費用
  4. 點選底下的Send按鈕完成交易

傳送QTUM

選擇手續費

接收Qtum

點選錢包左邊的Receive按鈕,進入接收Qtum的操作介面,可以管理用於接收Qtum地址。使用流程如下:

  1. 點選Request payment,出現一個對話方塊,點選close即可
  2. 點選Requested payment history欄目可以顯示剛才生成的地址資訊
  3. 點選Remove可以去除生成的地址資訊

管理接收地址

智慧合約

智慧合約(Smart Contract),是密碼學家Nick Szabo在1994年首次提出以數字形式定義的一系列承諾(promises),包括合約參與方可以在上面執行這些承諾的協議。智慧合約通過區塊鏈來執行,因此一旦設立指定後,能夠無需中介的參與自動執行。
Qtum支援使用Solidity語言進行智慧合約的編寫。Solidity寫好智慧合約的智慧合約,可以使用solc來編譯,也可以直接使用基於瀏覽器的編譯器,比如Remix Solidity IDE。下面通過一個簡單的例子來說明開發、部署智慧合約的過程。

智慧合約編寫和編譯

Qtum支援與EVM相容的智慧合約,編寫智慧合約最常用的語言是Solidity。編寫完智慧合約之後可以採用Remix Solidity IDE進行編譯,該工具一個基於瀏覽器的編譯器,其連結如下:ethereum.github.io/browser-sol…

這裡通過一個簡單的智慧合約例項,說明合約怎樣完成編譯,部署以及和合約互動。測試的智慧合約程式碼如下:

           pragma solidity ^0.4.11;
           contract Test {
                       uint256 public totalSupply = 0;
                       mapping (address => uint256) public balanceOf;    
                       function Test() { }    
                       modifier validAmount(uint256 _amount) {
                                 require(_amount > 0);
                                 _;
                         }  
                     function contribute()  public  payable  validAmount(msg.value) 
                    returns (uint256 amount) {
                         uint256 tokenAmount = msg.value/100000000;
                         totalSupply += tokenAmount;
                         balanceOf[msg.sender] += tokenAmount;
                         return tokenAmount;
                      }    
              }
複製程式碼

把以上程式碼拷貝到Remix Solidity IDE左邊的空白處,點選右邊Contract details就可以看到編譯生成的位元組碼(bytecode)。這是智慧合約編譯後的可執行二進位制程式碼,下面的部署就是用這個生成的位元組碼。部署智慧合約相當於是安裝一個軟體到作業系統,因此需要把智慧合約部署到量子鏈後,才能使用該智慧合約的服務。

使用Remix Solidity IDE編譯智慧合約

部署智慧合約

部署智慧合約需要訪問Qtum區塊鏈的節點,通過Qtum節點提供的cli命令列或RPC呼叫可以進行智慧合約相關的操作。

首先要執行Qtum全節點軟體qtumd,把編譯生成的位元組碼(bytecode)copy一份,然後使用qtum-cli呼叫createcontract可以把智慧合約部署到Qtum量子鏈上。

qtum-cli  createcontract  60606040526000600055341561001157fe5b5b5b5b6101b7806100236000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005157806370a0823114610077578063d7bb99ba146100c1575bfe5b341561005957fe5b6100616100df565b6040518082815260200191505060405180910390f35b341561007f57fe5b6100ab600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506100e5565b6040518082815260200191505060405180910390f35b6100c96100fd565b6040518082815260200191505060405180910390f35b60005481565b60016020528060005260406000206000915090505481565b60006000346000811115156101125760006000fd5b6305f5e1003481151561012157fe5b0491508160006000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508192505b5b5050905600a165627a7a723058203e478f327587dc2eb6995d102ce549279f911bc27074dc932ef8b81bad7bb0ba0029 3000000 0.0000005
複製程式碼

3000000 0.0000005是 gaslimit和gasprice引數,參考第2.3.1節知道者兩個引數可以不設定或可以改為其他的值。命令執行後或產生如下輸出:

{
  "txid": "52b3eef0fe0032f685974256972b340655501fc87adec4cffe2b96cc46446001",
  "sender": "qYcH9wHcd86LaDAAxquKPyfpmSraxAbBop",
  "hash160": "a5161fee8ff92457c0829889854888b45255f961",
  "address": "2d4b6564a012ae1383854ac48574c2248660d897"
}
複製程式碼

這個輸出是一個交易,所有合約相關的功能都是通過傳送交易觸發的,該交易在Qtum量子鏈上部署了地址為2d4b6564a012ae1383854ac48574c2248660d897的智慧合約。智慧合約的需要等待區塊對交易確認後,才在Qtum鏈上部署完成。

和智慧合約互動

和智慧合約的互動也需要訪問Qtum區塊鏈的節點,通過Qtum節點提供的cli命令列或RPC呼叫可以和智慧合約進行互動,使用智慧合約提供的服務。使用智慧合約比較簡單,首先是生成需要互動的函式或公共變數的ABI(Application Binary Interface)資料,之後使用sendtocontract傳送合約交易,完成和Qtum鏈上智慧合約互動。使用callcontract可以在本地呼叫智慧合約相關函式或公共變數,但其執行只在本地執行,不會影響到鏈上的智慧合約狀態。

ABI資料生成

ABI是和智慧合約互動的介面,為了使用上一節部署的合約,需要智慧合約相關函式和引數生成的資料(ABI資料),可以使用ethabi工具把函式和引數轉換成以上的”data”資料。

首先建立一個空檔案test.json,把Remix Solidity IDE右邊的Interface的內容放到檔案test.json上。比如上面的合約ABI如下:

[{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"contribute","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}]
複製程式碼
  • 生成與合約contribute()函式互動的資料 contribute()函式沒有引數,因此執行如下命令:
    ethabi encode function ~/test.json contribute
    複製程式碼

得到輸出資料:

d7bb99ba
複製程式碼
  • 生成與合約balanceOf(Address)函式互動的資料

balanceOf(Address)需要傳遞Address引數,使用選項-p指定,Address是一個20位元組的16進位制引數,使用ethabi執行:

ethabi encode function ./test.json balanceOf -p a5161fee8ff92457c0829889854888b45255f961
複製程式碼

得到輸出:

70a08231000000000000000000000000a5161fee8ff92457c0829889854888b45255f961
複製程式碼
  • 生成與合約公共變數totalSupply互動的資料

totalSupply是一個帶有public屬性的變數,因此雖然totalSupply不是一個函式,但也可以和它進行互動,同樣使用ethabi生成互動所需的資料:

ethabi encode function ./test.json totalSupply
複製程式碼

得到輸出:

 18160ddd
複製程式碼

使用sendtocontract和智慧合約互動

如果要呼叫鏈上的智慧合約,把執行結果儲存在鏈上,需要發起一個合約交易,這是通過sendtocontract來完成的。使用sendtocontract發起一個合約交易的格式如下:

sendtocontract "contractaddress" "data" (amount gaslimit gasprice senderaddress)
複製程式碼

其中“data”為上一節產生的ABI資料,因此要呼叫合約的contribute函式,採用如下的命令:

sendtocontract 2d4b6564a012ae1383854ac48574c2248660d897 d7bb99ba 2 1000000 0.0000004 qYcH9wHcd86LaDAAxquKPyfpmSraxAbBop
複製程式碼

d7bb99ba即為資料,2是這筆交易發生到智慧合約的QTUM數量,1000000是gaslimit,0.0000004是gasprice, qYcH9wHcd86LaDAAxquKPyfpmSraxAbBop是senderaddress。此處為了指定senderaddress,需要把前面的amount、gaslimit 、gasprice引數也指定,執行後命令會返回:

{
  "txid": "1e9742000cc5d261f18b3ecc41ffd44b37f965567127b1779fb7d48b12bdfcda",
  "sender": "qYcH9wHcd86LaDAAxquKPyfpmSraxAbBop",
  "hash160": "a5161fee8ff92457c0829889854888b45255f961"
}
複製程式碼

合約交易的執行需要新區塊打包和執行,因此檢視智慧合約的結果需要等待至少1個區塊的確認。

使用callcontract檢視智慧合約執行結果

雖然使用callcontract可以在本地呼叫智慧合約相關函式或公共變數,但其執行只在本地執行,不會儲存結果和影響到鏈上的智慧合約狀態。因此該功能一般用於檢視由sendtocontract發起的合約交易引起的智慧合約狀態改變結果。其格式如下: callcontract "address" "data" ( senderaddress )

比如要檢視a5161fee8ff92457c0829889854888b45255f961的balance使用:

callcontract 2d4b6564a012ae1383854ac48574c2248660d897 70a08231000000000000000000000000a5161fee8ff92457c0829889854888b45255f961
複製程式碼

命令返回:

{
  "address": "2d4b6564a012ae1383854ac48574c2248660d897",
  "executionResult": {
    "gasUsed": 23183,
    "excepted": "None",
    "newAddress": "2d4b6564a012ae1383854ac48574c2248660d897",
    "output": "0000000000000000000000000000000000000000000000000000000000000002",
    "codeDeposit": 0,
    "gasRefunded": 0,
    "depositSize": 0,
    "gasForDeposit": 0
  },
  "transactionReceipt": {
    "stateRoot": "cb3e98d8bfcde37e37df441915a3d6f50712a7e368f6e798cc804aa574fd6c27",
    "gasUsed": 23183,
    "bloom": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "log": [
    ]
  }
}
複製程式碼

在PC錢包上使用智慧合約

在PC錢包(qtum-qt軟體)上可以通過GUI實現和qtum-cli同樣的智慧合約的部署、互動等功能。

部署智慧合約

部署合約都是要和Qtum鏈上進行互動的,因此連線到一個全節點,由於PC錢包本身是一個全節點,因此不需要另外執行qtumd之類的節點。在PC錢包左邊點選Smart Contract按鈕出現智慧合約功能介面,點選Create後,把4.1節編譯的位元組碼拷貝在Bytecode輸入框,同時把ABI也放入對應的輸入框。對應qtum-cli createcontract命令引數,介面下面的GasLimit、GasPrice、和Sender Address可以設定。最後點選Create Contract按鈕,就會生成一個合約交易,把合約部署到Qtum鏈上,彈出的對話方塊顯示了傳送者、合約地址等相關資訊。

PC錢包部署智慧合約

和智慧合約互動

和智慧合約的互動,同樣要連線Qtum節點,通過PC錢包就可以了。生成需要互動的函式或公共變數的ABI資料可以參考4.3.1節。點選Sendto切換到合約交易生成介面,把Contract Address、ABI填好,從Functtion選擇要呼叫的函式,有函式引數的話,在address dest面填寫引數,GasLimit、GasPrice、和Sender Address可以根據需要設定。點選Send To Contract按鈕即生成了合約交易, 完成和Qtum鏈上智慧合約互動。

和智慧合約互動

檢視智慧合約執行結果

和callcontract一樣可以通過qt錢包在本地呼叫智慧合約相關函式或公共變數,其執行不會影響到鏈上的智慧合約狀態,一般用來檢視智慧合約在Qtum鏈上執行某個函式之後的結果。點選Call按鈕切換到本地執行合約介面,把Contract Address、、ABI填好,有函式引數的話,在address dest面填寫引數,從Functtion選擇要呼叫的函式,Sender Address可選設定,最後點選Call Contract完成智慧合約相關功能呼叫,合約執行的結果會在彈出的對話方塊中顯示出來。

本地呼叫智慧合約

與以太坊智慧合約的不同

msg.value

在 qtum 智慧合約中,msg.value 使用的單位是 Satoshi, 即聰, 1 qtum = 10^8 聰; 而在以太坊中,msg.value 使用的單位是 wei, 1 ether = 10^18 wei 。

如果你在 Qtum 智慧合約中使用了 ether 關鍵字,那麼它實際相當於10^10 qtum。

為了避免不必要的麻煩,請不要使用 wei、ether 等單位,而是直接使用數字。

在 Qtum 上發行合約代幣時, 推薦將 decimals 設定為 8 。

address 型別引數

呼叫智慧合約,傳遞address型別引數的時候,需要使用hash160地址,而不是Q開頭的qtum地址。可以使用qtum-cli gethexaddress命令將qtum地址轉換為hash160地址。

獲取 event log

啟動 qtumd 或者 qtum-qt 的時候使用 -logevents 引數,然後使用 qtum-cli searchlogs 或者 qtum-cli gettransactionreceipt 獲取 event log 。


相關文章