以客户端请求blockchain.block.get_header,传入参数区块高度为0为例:
#!/usr/bin/env python
import socket, json
from jsonrpc.jsonrpc2 import JSONRPC20Request, JSONRPC20Response
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1', 50003))
print('connected!')
request2 = JSONRPC20Request('blockchain.block.get_header', {'height':0}, 1 )
send_json = request2.json+'\n'
print(send_json)
client.send(send_json.encode('utf-8'))
response = client.recv(1024000)
print(response.decode('utf-8'))
当客户端请求发出之后,Electrumx服务端server/session.py中的ElectrumX负责接收和处理客户端传来的请求。
1、在set_protocol_handlers中设定客户端请求的方法名,设置名字和对应的Controller中的方法对应。
2、在Controller中找到对应的方法,在这个例子中因为客户端请求的是blockchain.block.get_header,则对应Controller中的block_get_header.
block_get_header中先是验证了参数的合法性,接着调用electrum_header获取头部信息
只接收大于0的参数
首先看缓存中是否有要查询的数据,如果没有则通过raw_header查询header的二进制数据,并加入到缓存,如果缓存中已经有则直接返回缓存中的数据。
缓存数据是放到pylru中的
raw_header返回未加工的header数据,在方法中调用了区块链处理器block_processer.py中的read_headers方法,read_headers方法传递的height是区块高度,1应该是代表只有一个头部信息
计算头部信息偏移位置,根据区块高度*区块头部字节数来计算
lib/util.py中的read方法:
使用divmod计算当前区块的header应该存放在哪个文件中,且计算偏移量,比如第335001,每个区块头部是80字节,所以start为335001*80=26800080,self.file_size为固定值16000000(每个header存储文件的大小,单位字节),所以file_num, offset = divmod(start, self.file_size),用26800080除以16000000得到商为1(file_num),余10800080(offset),所以第0个区块存放在meta/headers00中,第335001个区块存放在meta/headers01中。
至此,取到了第0个区块的header信息,回到coins.py中的electrum_header方法,解析出返回的二进制数据
第0个区块取得的header数据为:
b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\xa3\xed\xfdz{\x12\xb2z\xc7,>gv\x8fa\x7f\xc8\x1b\xc3\x88\x8aQ2:\x9f\xb8\xaaK\x1e^J)\xab_I\xff\xff\x00\x1d\x1d\xac+|'
第335001个区块取得的header数据为:
b"\x02\x00\x00\x00\xe6@w\x9e\x8by=\xd9C@\x7f\xf4\xe7\xea\x8b\xec\x07(b\xa2BLw\x0f\x00\x00\x00\x00\x00\x00\x00\x00\t\xe7\x1f@\xec\xc0\x03\xf2j\x10\x94\x18n\xcf\xd6\xcfg\xe5)\xa9@\xb9'\xe5u\xae\x02/,\xf4:\x912\x8f\x94T|\xdd\x1b\x18\xeb\r\x81["