equity合約簡介
equity是bytom用於表達合約程式而使用的高階語言,主要用於描述bytom鏈上特定的資產:·區塊鏈上的所有資產都是鎖定在合約program中, 資產值value(即UTXO)一旦被一個合約解鎖unlock,僅僅是為了被一個或多個其他合約來進行鎖定lock。·合約保護資產value(即UTXO)的方式是採用執行虛擬機器並透過verify指令來驗證的交易要花費這個資產value是否達到了我的條件。合約組成contract ContractName ( parameters ) locks value { clauses }·ContractName 合約名,使用者自定義·parameters 合約引數列表,其型別名必須符合合約語言的基本型別·value 資產值(即UTXO的資產型別和對應的值)識別符號,使用者可以自定義·clauses 條款(即函式)列表(一個或多個)條款(函式)組成clause ClauseName ( parameters ) { statements }或clause ClauseName ( parameters ) requires name : amount of asset { statements }·ClauseName 條款/函式名,使用者自定義·parameters 條款/函式引數列表·payments 花費UTXO需要的其他限制條件。例如進行幣幣交易的時候需要驗證交易的另一方能夠提供對應的資產值,該限制條件的使用場景主要為不同資產型別的合約交易語句組成statements 合約語句(一條或多條),程式碼語句只能是verify、lock和unlock·verify語句 模式如verify expression,其中expression的結果必須是bool型別,為true才能繼續往下執行·unlock語句 模式如unlock value,其中value表示對應的資產值·lock語句 模式如lock value with program,其中value表示對應的資產值,而program必須為Program基本型別合約的基本型別:(Time型別暫已停用) Amount Asset Boolean Hash Integer Program PublicKey Signature String內建函式:(涉及時間的內建函式before和after暫已停用,替代方法為驗證區塊高度的函式below和above)·abs(n) 返回數值n的絕對值.·min(x, y) 返回兩個數值x和y中最小的一個.·max(x, y) 返回兩個數值x和y中最大的一個.·size(s) 返回任意型別的位元組大小size.·concat(s1, s2) 返回連線兩個字串s1和s2生成新的字串.·concatpush(s1, s2) 將兩個字串型別的虛擬機器執行操作碼s1和s2連線起來(即將s2拼接在s1的後面),然後將他們push到棧中. 該操作函式主要用於巢狀合約中.·below(height) 判斷當前區塊高度是否低於引數height,如果是則返回true,否則返回false.·above(height) 判斷當前區塊高度是否高於引數height,如果是則返回true,否則返回false.·sha3(s) 返回byte型別字串引數s的SHA3-256的雜湊運算結果.·sha256(s) 返回byte型別字串引數s的SHA-256的雜湊運算結果.·checkTxSig(key, sig) 根據一個PublicKey和一個Signature驗證交易的簽名是否正確.·checkTxMultiSig([key1, key2, ...], [sig1, sig2, ...]) 根據多個PublicKey和多個Signature驗證交易的多重簽名是否正確。合約交易構造流程合約引數構造合約引數主要涉及兩個方面,一個是編譯合約contract中的引數,另一個是解鎖合約clause中的引數。合約的基本型別已做簡單描述,對應編譯合約的API介面compile中引數型別只有如下3種:·boolean - 布林型別的合約引數,對應的基本型別是Boolean.·integer - 整數型別的合約引數,對應的基本型別包括:Integer、Amount.·string - 字串型別的合約引數,對應的基本型別包括:String、Asset、Hash、Program、PublicKey.注意事項:·編譯合約API介面compile只需要使用contract中的引數·解鎖合約只需要提供clause中的引數·Signature型別只能在clause的引數列表中出現,不能出現在編譯合約的API中·所有string型別的字串都是必須以十六進位制位元組的string形式出現,否則呼叫編譯合約API的時候會報錯如果合約引數中有Publickey和Signature(配套使用),那麼獲取這些引數需要呼叫list-pubkeys介面獲取。Signature只能出現在clause中,表示該引數僅僅在解鎖合約的時候才會被使用,由於目前對交易的簽名必須透過sign-transaction介面才能獲取簽名結果,所以解鎖的時候只需提供簽名的引數root_xpub和derivation_path即可,需要注意的是這些引數需要跟驗證簽名pubkey匹配起來,否則合約也會執行失敗。其中list-pubkeys的引數如下:String - account_id, 賬戶ID.其請求和響應的json格式如下:// Request
{
"account_id": "0G1JIR6400A02"
}
// Result
{
"pubkey_infos": [
{
"derivation_path": [
"010100000000000000",
"0300000000000000"
],
"pubkey": "c37d5531f393bc6a3568628c0c0e17801ea452e75d604deb01403c4b161659a3"
},
{
"derivation_path": [
"010100000000000000",
"0200000000000000"
],
"pubkey": "117d12e84bb19e956451e0b1eb2bffc662ecb7aac7e63d77e524ddd467eb3617"
},
{
"derivation_path": [
"010100000000000000",
"0100000000000000"
],
"pubkey": "e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e78"
}
],
"root_xpub": "5c6145b241b1147987565719657a0506ebb417a2e110a235a42cfb40951880f447432f930ce9fd1a6b7e51b3ddbfdc7adb57d33448f93c0defb4de630703a144"
}
編譯合約
呼叫API介面compile編譯合約。如果合約contract語句上有引數contract parameters的話,可以在呼叫編譯合約API介面compile的時候加上相關引數進行例項化,這樣編譯後返回的結果中program欄位會限定合約的解鎖引數,否則返回的program僅僅是合約的執行步驟流程,在缺少合約引數的情況下,需要使用者自定義相關的合約引數,否則合約鎖定的資產會存在洩漏的風險。
引數:
·String - contract, 合約內容.
·Array of Object - args, 合約引數結構體(陣列型別).
·Boolean - boolean, 布林型別的合約引數.
·Integer - integer, 整數型別的合約引數.
·String - string, 字串型別的合約引數.
以LockWithPublicKey為例,其請求和響應的json格式如下:
// Request
{
"contract": "contract LockWithPublicKey(publicKey: PublicKey) locks locked { clause unlockWithSig(sig: Signature) { verify checkTxSig(publicKey, sig) unlock locked }}",
"args": [
{
"string": "e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e78"
}
]
}
// Result
{
"name": "LockWithPublicKey",
"source": "contract LockWithPublicKey(publicKey: PublicKey) locks locked { clause unlockWithSig(sig: Signature) { verify checkTxSig(publicKey, sig) unlock locked }}",
"program": "20e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e787403ae7cac00c0",
"params": [
{
"name": "publicKey",
"type": "PublicKey"
}
],
"value": "locked",
"clause_info": [
{
"name": "unlockWithSig",
"args": [
{
"name": "sig",
"type": "Signature"
}
],
"value_info": [
{
"name": "locked"
}
],
"block_heights": [],
"hash_calls": null
}
],
"opcodes": "0xe9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e78 DEPTH 0xae7cac FALSE CHECKPREDICATE",
"error": ""
}
鎖定合約
lock(鎖定)合約,即部署合約,其本質是呼叫build-transaction介面將資產傳送到合約特定的program,只需將接收方control_program設定為指定合約即可,構造鎖定合約交易的模板如下:(注意:合約交易暫時不支援接收方資產為BTM資產的交易)
// Request
{
"base_transaction": null,
"actions": [
{
"account_id": "0G1JIR6400A02",
"amount": 20000000,
"asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"type": "spend_account"
},
{
"account_id": "0G1JIR6400A02",
"amount": 900000000,
"asset_id": "1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c22",
"type": "spend_account"
},
{
"amount": 900000000,
"asset_id": "1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c22",
"control_program": "20e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e787403ae7cac00c0",
"type": "control_program"
}
],
"ttl": 0,
"time_range": 1521625823
}
// Result
{
"raw_transaction": "0701dfd5c8d505020161015f150ec246dc739a8c4c3f7b4083ededcb2854ca221e437a49f23ec84c7c47ea80ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8099c4d599010001160014726e902e30525e01f0157f12be476c904060383b01000160015ed53c1f3388681f62ae778ac8a54c2b091bbdc91d68ec1e94b20aa2183484f8331e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c2280c8afa02501011600145de3c504b41019d11698d572b1a37d9a4c9118c1010003013effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80bfffcb990101160014310c2265e8e3b7057a62caf09a9f907763f369ea00013d1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c2280f69bf32101160014d0d18752a276c94b25f920b02a8edff251b16b7600014f1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c2280d293ad03012820e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e787403ae7cac00c000",
"signing_instructions": [
{
"position": 0,
"witness_components": [
{
"type": "raw_tx_signature",
"quorum": 1,
"keys": [
{
"xpub": "5c6145b241b1147987565719657a0506ebb417a2e110a235a42cfb40951880f447432f930ce9fd1a6b7e51b3ddbfdc7adb57d33448f93c0defb4de630703a144",
"derivation_path": [
"010100000000000000",
"0100000000000000"
]
}
],
"signatures": null
},
{
"type": "data",
"value": "e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e78"
}
]
},
{
"position": 1,
"witness_components": [
{
"type": "raw_tx_signature",
"quorum": 1,
"keys": [
{
"xpub": "5c6145b241b1147987565719657a0506ebb417a2e110a235a42cfb40951880f447432f930ce9fd1a6b7e51b3ddbfdc7adb57d33448f93c0defb4de630703a144",
"derivation_path": [
"010100000000000000",
"0700000000000000"
]
}
],
"signatures": null
},
{
"type": "data",
"value": "54df681ac3174a11d4456265641a204e04f64b8f860f37bf5584cf4187f54e99"
}
]
}
],
"allow_additional_actions": false
}
構建交易成功之後,便可以對交易進行簽名sign-transaction(簽名成功的標誌是返回結果signing_instructions中所有包含簽名型別的signatures欄位有值且個數與quorum的值相等),然後提交交易submit-transaction到交易池中,等待交易被打包上鍊
查詢合約utxo
部署合約交易傳送成功之後,接下來便需要對合約鎖定的資產進行解鎖,解鎖合約之前需要找到合約的UTXO。
可以透過呼叫API介面list-unspent-outputs來查詢,在查合約UTXO的情況下必須將smart_contract設定為true,否則會查不到,其引數如下:
String - id, UTXO對應的outputID.
Boolean - smart_contract, 是否展示合約的UTXO,預設不顯示.
對應的輸入輸出結果如下:
// Request
curl -X POST list-unspent-outputs -d '{"id": "413d941faf5a19501ab4c06747fe1eb38c5ae76b74d0f5af524fc40ee6bf7116", "smart_contract": true}'
// Result
{
"account_alias": "",
"account_id": "",
"address": "",
"amount": 900000000,
"asset_alias": "GOLD",
"asset_id": "1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c22",
"change": false,
"control_program_index": 0,
"id": "413d941faf5a19501ab4c06747fe1eb38c5ae76b74d0f5af524fc40ee6bf7116",
"program": "20e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e787403ae7cac00c0",
"source_id": "c9680e6dd5e9ae7f825fe7edab9fa35c119eb7feab0ab4e426c84a579daf4ef9",
"source_pos": 2,
"valid_height": 0
}
找到對應的合約UTXO之後,可以透過API介面decode-program解析合約的引數資訊,使用者可以根據已有的引數資訊判斷該合約能否解鎖
解鎖合約
unlock(解鎖)合約,即呼叫合約,其本質是透過給交易新增相應的合約引數以便合約程式program在虛擬機器中執行成功,目前合約相關的引數都可以透過build-transaction中的Action結構spend_account_unspent_output中的陣列引數arguments進行新增,其中引數主要有兩種型別:
·rawTxSigArgument 簽名相關的引數,主要包含主公鑰xpub和其對應的派生路徑derivation_path,而待驗證的publickey是透過該主公鑰和派生路徑生成的子公鑰生成的(這些引數可以透過API介面list-pubkeys獲取)
·xpub 主公鑰
·derivation_path 派生路徑,為了形成子私鑰和子公鑰
·dataArgument 其他型別的引數,其數值是[]byte型別的string格式
以合約LockWithPublicKey為例,其解鎖合約交易的模板如下:
// Request
{
"base_transaction": null,
"actions": [
{
"type": "spend_account_unspent_output",
"output_id": "413d941faf5a19501ab4c06747fe1eb38c5ae76b74d0f5af524fc40ee6bf7116",
"arguments": [
{
"type": "raw_tx_signature",
"raw_data": {
"xpub": "5c6145b241b1147987565719657a0506ebb417a2e110a235a42cfb40951880f447432f930ce9fd1a6b7e51b3ddbfdc7adb57d33448f93c0defb4de630703a144",
"derivation_path": [
"010100000000000000",
"0100000000000000"
]
}
}
]
},
{
"type": "control_program",
"asset_id": "1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c22",
"amount": 900000000,
"control_program": "0014726e902e30525e01f0157f12be476c904060383b"
},
{
"type": "spend_account",
"asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"amount": 5000000,
"account_id": "0G1JIR6400A02"
}
],
"ttl": 0,
"time_range": 1521625823
}
// Result
{
"raw_transaction": "0701dfd5c8d5050201720170c9680e6dd5e9ae7f825fe7edab9fa35c119eb7feab0ab4e426c84a579daf4ef91e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c2280d293ad0302012820e9108d3ca8049800727f6a3505b3a2710dc579405dde03c250f16d9a7e1e6e787403ae7cac00c001000160015e8412e8e8c359683f1f5f3a7308b084022f1f149dab176e6e6e8daada895d0e29ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0c6c6944f00011600141313e974d19f3d37db29a212d75b4c763e42f433010002013d1e074b22ed7ae8470c7ba5d8a7bc95e83431a753a17465e8673af68a82500c2280d293ad0301160014726e902e30525e01f0157f12be476c904060383b00013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0b095924f011600147076c737d92621e0033899a54d02fa79f362922700",
"signing_instructions": [
{
"position": 0,
"witness_components": [
{
"type": "raw_tx_signature",
"quorum": 1,
"keys": [
{
"xpub": "5c6145b241b1147987565719657a0506ebb417a2e110a235a42cfb40951880f447432f930ce9fd1a6b7e51b3ddbfdc7adb57d33448f93c0defb4de630703a144",
"derivation_path": [
"010100000000000000",
"0100000000000000"
]
}
],
"signatures": null
}
]
},
{
"position": 1,
"witness_components": [
{
"type": "raw_tx_signature",
"quorum": 1,
"keys": [
{
"xpub": "5c6145b241b1147987565719657a0506ebb417a2e110a235a42cfb40951880f447432f930ce9fd1a6b7e51b3ddbfdc7adb57d33448f93c0defb4de630703a144",
"derivation_path": [
"010100000000000000",
"0300000000000000"
]
}
],
"signatures": null
},
{
"type": "data",
"value": "c37d5531f393bc6a3568628c0c0e17801ea452e75d604deb01403c4b161659a3"
}
]
}
],
"allow_additional_actions": false
}
構建交易成功之後,便可以對交易進行簽名sign-transaction(簽名成功的標誌是返回結果signing_instructions中所有包含簽名型別的signatures欄位有值且個數與quorum的值相等),然後提交交易submit-transaction到交易池中,等待交易被打包上鍊。
更多區塊鏈資訊:http://www.qukuaiwang.com.cn/news