submit_block如何提交区块,具体参数是怎样的格式
submit:
{
"id": 0,
"jsonrpc": "2.0",
"method": "submit_block",
"params": ["0", {
"header": {
"chain_root": "0xe016b02274c92686b2704bb341dfe3b5e1c157051dd79ba9ec59accaf4b1b88a",
"dao": "0x01000000000000000000c16ff28623000033da2dbb84070000c581a97f7a0100",
"difficulty": "0x100",
"epoch": "0x0",
"nonce": "0x6bce77da33646101",
"number": "0x2",
"parent_hash": "0x4fbea9b6118eb0238eb7ba04b550f84a3f625f23f33002ae74f582fc85f2a298",
"proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x16d3d84b8b7",
"transactions_root": "0xc0a459928f3adce5aa509bfc6177955445e9585ab9f1f145e9514a8f4e4bdc6f",
"uncles_count": "0x0",
"uncles_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"version": "0x0",
"witnesses_root": "0x88c3bc4a11972459ab94c9d0ef2ca5bc1cbb6b1f61cc8ec056ca185bbaa20e78"
},
"proposals": [],
"transactions": [{
"cell_deps": [],
"header_deps": [],
"inputs": [{
"previous_output": {
"index": "0xffffffff",
"tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"since": "0x2"
}],
"outputs": [{
"capacity": "0x1d1a94a200",
"lock": {
"args": ["0xb2e61ff569acf041b3c2c17724e2379c581eeac3"],
"code_hash": "0x1892ea40d82b53c678ff88312450bbb17e164d7a3e0a90941aa58839f56f8df2",
"hash_type": "type"
},
"type": null
}],
"outputs_data": ["0x"],
"version": "0x0",
"witnesses": [{
"data": ["0x1892ea40d82b53c678ff88312450bbb17e164d7a3e0a90941aa58839f56f8df201", "0x418ac4485a3dbe8221321b249631cf8491b31fd1"]
}]
}],
"uncles": []
}]
}
submit_block 所需要的参数有2个,一个是 work_id (通过 get_block_template 获取到的数据里面有这个值),另外一个是 block ,它和 get_block 获得的数据结构是一样的,你可以通过 get_block 来参考看看。
很抱歉目前关于 miner 的这2个RPC都还没有文档,我们会尽快补上。
submitWork提交时有几个字段内容需要确认:
-
header的hash字段是如何生成的,是否就是下发任务对应的header_hash
-
header的proposals_hash是否是固定值:0x0000000000000000000000000000000000000000000000000000000000000000
-
header的transactions_root,uncles_hash,witnesses_root 是如何生成的
-
transactions: 是否是get_block_template结果的cellbase的data内容
-
proposals与uncles:是否是get_block_template结果对应字段内容
- header_hash 是 block hash ,当 nonce 填入 block 之后,hash 整个 block 生成
- proposals_hash 不固定,根据 proposal 的交易树生成,也就是 template 给过来的值
3、4、5 都是 template 原值
proposals_hash是如何生成的呢,有c/c++, python,java的实现版本吗
chain_root,transactions_root,uncles_hash,witnesses_root这几个字段是怎样生成的?
麻烦您能否提供一个:1.从get_block_template获取数据 —> 2.矿工提交数据给矿池-------> 3.矿池再submitWork这3个过程的案例真实数据,便于我们开发前用伪代码测试整个过程的可行性。
现在主要是没有真实案例的header_hash字段数据,想提前用c语言伪代码验证这个过程。
ckb 本身没有矿池协议,矿池是外挂的系统,与 ckb 本身没有直接关系。
验证数据可以使用 dev chain
https://github.com/nervosnetwork/ckb/blob/develop/docs/ckb-core-dev.md
目前按照文档:ckb-core-dev.md 已经成功运行到make integration这个命令,接着我怎么做?
- CKB 里面所有的 hash 都是将结构做了一次序列化之后,然后对序列化后的 bytes 做一次 blake2b , header 序列化 schema 在这里:
https://github.com/nervosnetwork/ckb/blob/rc/v0.20/util/types/schemas/ckb.mol#L83-L96
对应的序列化文档在这里:
还没有被正式合并到 rfc 里面,可能还有一些小调整。
对应的实现,可以参考 ckb 不同语言的 sdk,比如 java:
-
proposals_hash 是对 block 包含的 proposal ids 计算出 merkle root,我们用的 merkle tree 稍微和其他实现有点不同,参考:
https://github.com/nervosnetwork/merkle-tree -
transactions_root,uncles_hash,witnesses_root 也都是算不同对象的 merkle root,相关的代码在这里:
https://github.com/nervosnetwork/ckb/blob/rc/v0.20/util/types/src/extension/shortcuts.rs#L154-L158
请问是怎样获取下面的数据的,对下面的数据序列号后去计算head_hash
struct RawHeader {
version: Uint32,
uncles_count: Uint32,
timestamp: Uint64,
number: Uint64,
epoch: Uint64,
parent_hash: Byte32,
transactions_root: Byte32,
witnesses_root: Byte32,
proposals_hash: Byte32,
difficulty: Byte32,
uncles_hash: Byte32,
dao: Byte32,
}
序列化的数据为:00000000000000008401554d6d010000becb01000000000052000000000000009c58871631763190a7e505ea5f694e033f03c4fe07f1757de3f2460e2cd978764913bbe1c058454b519b8e5fd3e582d3f98dd9edd21ee3f70e633090d8b63573eb2d955d8a07236d1978b3aaf283c0ad916b57b37ae81673eb87a94b7ad4e23e00000000000000000000000000000000000000000000000000000000000000002b46a1411127000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000e136d965358d2c0069f0f90005ee6b0000cbf720915a03000000000000000000
调用blake2b算法得到head_hash,结果是正确的吗?
a3d3125563fc9c87a9909544609132f8b8b0284109df43b9de95f8496526114c
transactions_root,uncles_hash,witnesses_root 能讲一下大体计算流程吗,因为不懂rust语言,现在用c语言开发
transactions_roots 是对所有 transactions 的 hash 算出他们的 merkle root,我们用的 merkle tree 排列方法和其他常见的 merkle tree有少许不同,是一个完全二叉树,你可以先看一下是怎么排列计算的:
witnesses_root 是对所有的 transations witnesses hash 算 merkle root
uncles_hash 是对所有的 uncle 序列化之后做一次 blake2b
如果"uncles": [],那么计算uncles_hash时候,采用blake2b算法,in参数为""吗? key为多少? keylen为多少?
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
如果 uncles 为空,不需要进行 blake2b 计算,直接返回全0
谢谢,意思就是计算uncles_hash时候,如果有数据的话,就是把arr里面的每个数据进行序列化,再,拼接起来作为in参数。
现在整个挖矿过程只留存一个问题没有解决: 计算witnesses_root,因为不了解rust语言,现在开发使用c语言,请问是否会有这种c实现的计算merkle root算法?
目前没有C的代码,你暂时只能参考文档和rust 的实现来做一个 c 的计算。
算两个叶子节点上一层就是把2个值做一次 blake2b,参考代码:
参考 merkle tree 项目里面的左边这个图:
with 6 items with 7 items
B0 -- node 0 B0 -- node 0
/ \ / \
/ \ / \
/ \ / \
/ \ / \
B1 -- node 1 B2 -- node 2 B1 -- node 1 B2 -- node 2
/ \ / \ / \ / \
/ \ / \ / \ / \
/ \ / \ / \ / \
B3(3) B4(4) TO(5) T1(6) B3(3) B4(4) B5(5) T0(6)
/ \ / \ / \ / \ / \
T2 T3 T4 T5 T1 T2 T3 T4 T5 T6
(7) (8) (9) (10) (7) (8) (9)(10)(11) (12)
假设现在有6个witness hash,排列是 [T0, T1, T2, T3, T4, T5]
那么要先计算 T2和T3 的上一层 B3,然后算 T4和T5 的上一层 B4,
依次类推,直到算出 B0,就是 merkle root