Submit_block如何提交区块

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都还没有文档,我们会尽快补上。

1 Like

submitWork提交时有几个字段内容需要确认:

  1. header的hash字段是如何生成的,是否就是下发任务对应的header_hash

  2. header的proposals_hash是否是固定值:0x0000000000000000000000000000000000000000000000000000000000000000

  3. header的transactions_root,uncles_hash,witnesses_root 是如何生成的

  4. transactions: 是否是get_block_template结果的cellbase的data内容

  5. proposals与uncles:是否是get_block_template结果对应字段内容

  1. header_hash 是 block hash ,当 nonce 填入 block 之后,hash 整个 block 生成
  2. 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这个命令,接着我怎么做?

  1. 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:

  1. proposals_hash 是对 block 包含的 proposal ids 计算出 merkle root,我们用的 merkle tree 稍微和其他实现有点不同,参考:
    https://github.com/nervosnetwork/merkle-tree

  2. 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


请问调用rust的merkle是怎么计算witnesses_root的吗?

如果"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