1.Execute函数执行
调用解析区块函数
errcode_rpc, trans_list, block_list, new_height, max_height = self.parallel[i]['rpc'].traverse_new_block(self.parallel[i]['filter'],blocks[i], 50)
1.1.traverse_new_block函数里包括filter_to
对lock_address(锁定合约地址)进行校验
def traverse_new_block(self, filter_to, sync_number, count):
filter_to 是经过校验的 校验如下
##首先调用合约进行查询 获取链上信息
def get_parallel_chain(self,chain_id):
return self.rpc.get_raw_contract(self.inter_reg_addr,self.abi_reg).caller.queryParallelChain(chain_id)
##相应的从数据库进行查询 获取数据库相应的信息
chain,gate = self.db.get_chain(list(self.config['parallel-chain'].keys()))
##根据平行链ID调用合约查询对应数据 比对 锁定lock合约地址 以及 SPV合约地址 是否和数据库内相同
result = self.get_parallel_chain(id)
if chain[id][4] != result[3]:
logging.info("parallel "+str_id+" lock address not match, db("+chain[id][4]+") query("+result[3]+")")
continue
if chain[id][7] != result[1]:
logging.info("parallel "+str_id+" spv address not match, db("+chain[id][7]+") query("+result[1]+")")
continue
1.2 traverse_new_block内还包括
block = self.get_block(i) 获取当前区块信息,为后面进行交易信息遍历准备
def get_block(self, number):
return self.web3.eth.getBlock(number)
返回值 - 区块对象:
- Number - 区块号。当这个区块处于pending将会返回null。
- hash - 字符串,区块的哈希串。当这个区块处于pending将会返回null。
- parentHash - 字符串,32字节的父区块的哈希值。
- nonce - 字符串,8字节。POW生成的哈希。当这个区块处于pending将会返回null。
- sha3Uncles - 字符串,32字节。叔区块的哈希值。
- logsBloom - 字符串,区块日志的布隆过滤器9。当这个区块处于pending将会返回null。
- transactionsRoot - 字符串,32字节,区块的交易前缀树的根。
- stateRoot - 字符串,32字节。区块的最终状态前缀树的根。
- miner - 字符串,20字节。这个区块获得奖励的矿工。
- difficulty - BigNumber类型。当前块的难度,整数。
- totalDifficulty - BigNumber类型。区块链到当前块的总难度,整数。
- extraData - 字符串。当前块的extra data字段。
- size - Number。当前这个块的字节大小。
- gasLimit - Number,当前区块允许使用的最大gas。
- gasUsed - 当前区块累计使用的总的gas。
- timestamp - Number。区块打包时的unix时间戳。
- transactions - 数组。交易对象。或者是32字节的交易哈希。
- uncles - 数组。叔哈希的数组。
- 例子
var info = web3.eth.getBlock(3150);
console.log(info);
/*
{
"number": 3,
"hash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46",
"parentHash": "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88",
"nonce": "0xfb6e1a62d119228b",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"transactionsRoot": "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee",
"stateRoot": "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb",
"miner": "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty": BigNumber,
"totalDifficulty": BigNumber,
"size": 616,
"extraData": "0x",
"gasLimit": 3141592,
"gasUsed": 21662,
"timestamp": 1429287689,
"transactions": [
"0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b"
],
"uncles": []
}
*/
1.3 def traverse_new_block(self, filter_to, sync_number, count):内 交易处理部分
根据交易hash获取对应交易详细信息
判断当前区块内是否和对应filter_to相等 此时比对为lock_address
相等则将对应交易加入transaction_list
此时我们得到 transaction_list为满足要求的交易 并将其返回
for j in transaction:
tx = self.get_tx_by_hash(j)
if filter_to != None:
tx_detect = self.convert_common_tx(dict(tx))
if tx_detect['to'] not in filter_to:
continue
tx = dict(tx)
tx["time"] = tx_time
transaction_list.append(tx)
其中 get_tx_by_hash(j)该函数为web3.py提供
def get_tx_by_hash(self, hash):
return self.web3.eth.getTransaction(hash)
返回值:
一个Promise对象,其解析值为具有给定哈希值的交易对象,该对象具有如下字段:
- hash 32 Bytes - String: 交易的哈希值
- nonce - Number: 交易发送方在此交易之前产生的交易数量
- blockHash 32 Bytes - String: 交易所在块的哈希值。如果交易处于pending状态,则该值为null
- blockNumber - Number: 交易所在块的编号,如果交易处于pending状态,则该值为null
- transactionIndex - Number: 交易在块中的索引位置,如果交易处于pending状态,则该值为null
- from - String: 交易发送方的地址
- to - String: 交易接收方的地址。对于创建合约的交易,该值为null
- value - String: 以wei为单位的转账金额
- gasPrice - String: 发送方承诺的gas价格,以wei为单位
- gas - Number: 发送方提供的gas用量
- input - String: 随交易发送的数据
示例代码:
web3.eth.getTransaction('0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b§234')
.then(console.log);
> {
"hash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b",
"nonce": 2,
"blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46",
"blockNumber": 3,
"transactionIndex": 0,
"from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value": '123450000000000000',
"gas": 314159,
"gasPrice": '2000000000000',
"input": "0x57cb2fc4"
}
2. 将处理好的交易列表信息返回赋值给trans_list
在excute函数当中 调用process_tx函数对经过过滤的交易列表等进行处理
self.process_tx(self.parallel[i]['rpc'],i,trans_list,new_height,max_height)
首先在process_tx函数内 对交易进行解析 判断是否调用 函数名称 在methods当中,不是则更新
methods = ['preLock','unLock','lock']
for j in methods:
result, params_list = rpc.parse_tx_input(newtx['to'],newtx['input'],self.parallel[id]['abi_lock'],j)
if result == True:
if 'method' not in params_list:
params_list = {
'method': j,
'params': params_list
}
break
调用函数如下
def parse_tx_input(self, contract_address, input, abi, func):
contract_call = self.web3.eth.contract(address=Web3.toChecksumAddress(contract_address), abi=abi)
result = contract_call.decode_function_input(input)
find = False
for i in result:
if str(i).find("Function " + func) >= 0:
find = True
continue
if find:
return True, i
return False, ""
ps.其中涉及web3.py函数 Contract.decode_function_input(data) 的例子
Contract.decode_function_input(data)
解码用于调用智能合约函数的交易数据,并将ContractFunction和已解码的参数作为 dict 返回。
>>> transaction = w3.eth.getTransaction('0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56')
>>> transaction.input
'0x612e45a3000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000116c6f6e656c792c20736f206c6f6e656c7900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
>>> contract.decode_function_input(transaction.input)
(<Function newProposal(address,uint256,string,bytes,uint256,bool)>,
{'_recipient': '0xB656b2a9c3b2416437A811e07466cA712F5a5b5a',
'_amount': 0,
'_description': b'lonely, so lonely',
'_transactionData': b'',
'_debatingPeriod': 604800,
'_newCurator': True})
之后进行数据格式处理,调用插入更新数据库操作 并将其type字段赋予1-6代表跨链交易进行到了哪步
self.db.update_chain(id,new_height,max_height,commited,newlist)

个人博客地址 https://www.b2bchain.cn/6369.html
区块链上跨链交易 数据成功进行 解析并存储于数据库