比原链(Bytom)合约交易构造流程
发布:中币网 时间:2018-07-26 21:04:08 加入收藏 打赏
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到交易池中,等待交易被打包上链。
来源:区块网
来源:中币网 https://www.zhongbi.net/news/blocknews/98627.html 声明:登载此文仅出于分享区块链知识,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不构成投资建议。投资者据此操作,风险自担。 此文如侵犯到您的合法权益,请联系我们3111859717@qq.com,我们将第一时间处理。