Commit 01c462c0 authored by mdj33's avatar mdj33 Committed by vipwzw

para cross tx result bitmap improve

parent b15384c1
......@@ -982,15 +982,19 @@ func rollbackCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []by
}
func getCrossTxHashsByRst(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus) ([][]byte, []byte, error) {
//只获取跨链tx
cfg := api.GetConfig()
//支持带版本号的跨链交易bitmap
//1.如果等于0,是老版本的平行链,按老的方式处理. 2. 如果大于0等于ver,新版本且没有跨链交易,不需要处理. 3. 大于ver,说明有跨链交易按老的方式处理
if len(status.CrossTxResult) == pt.ParaCrossStatusBitMapVerLen {
return nil, nil, nil
}
rst, err := hex.DecodeString(string(status.TxResult))
if err != nil {
clog.Error("getCrossTxHashs decode rst", "CrossTxResult", string(status.TxResult), "paraHeight", status.Height)
return nil, nil, types.ErrInvalidParam
}
clog.Debug("getCrossTxHashsByRst", "height", status.Height, "txResult", string(status.TxResult))
cfg := api.GetConfig()
if !cfg.IsDappFork(status.MainBlockHeight, pt.ParaX, pt.ForkParaAssetTransferRbk) {
if len(rst) == 0 {
return nil, nil, nil
......@@ -1010,8 +1014,6 @@ func getCrossTxHashsByRst(api client.QueueProtocolAPI, status *pt.ParacrossNodeS
}
paraCrossHashs := FilterParaCrossTxHashes(paraAllTxs)
crossRst := util.CalcBitMapByBitMap(paraCrossHashs, baseHashs, rst)
clog.Debug("getCrossTxHashsByRst.crossRst", "height", status.Height, "txResult", common.ToHex(crossRst), "len", len(paraCrossHashs))
return paraCrossHashs, crossRst, nil
}
......
......@@ -6,6 +6,7 @@ package executor
import (
"bytes"
"math/big"
"encoding/hex"
......@@ -230,12 +231,27 @@ func setMinerTxResult(cfg *types.Chain33Config, payload *pt.ParacrossMinerAction
return nil
}
//带版本号编码的bitmap,版本号占4bit位,除去版本号位,最高位为跨链交易个数,后面的则是交易结果bitmap
//比如00011110, 版本号为0001,1110的最高位1索引为3,代表后面3个交易,三个交易110代表第0个交易是失败的,其余的是ok的
//如果没有数量表示,在所有跨链交易都是失败的时候,返回的是个空值,无法区分是失败还是无交易
func getCrossAssetTxBitMap(crossAssetTxHashs, allTxHashs [][]byte, receipts []*types.ReceiptData) string {
rst := pt.ParaCrossStatusBitMapVer1
if len(crossAssetTxHashs) > 0 {
crossTxBitmap := util.CalcBitMap(crossAssetTxHashs, allTxHashs, receipts)
val := big.NewInt(0)
val.SetBytes(crossTxBitmap)
val.SetBit(val, len(crossAssetTxHashs), 1)
rst += val.Text(2)
}
return rst
}
func setMinerTxResultFork(cfg *types.Chain33Config, status *pt.ParacrossNodeStatus, txs []*types.Transaction, receipts []*types.ReceiptData) error {
isCommitTx := make(map[string]bool)
var curTxHashs [][]byte
var allTxHashs [][]byte
for _, tx := range txs {
hash := tx.Hash()
curTxHashs = append(curTxHashs, hash)
allTxHashs = append(allTxHashs, hash)
if cfg.IsMyParaExecName(string(tx.Execer)) && bytes.HasSuffix(tx.Execer, []byte(pt.ParaX)) {
var payload pt.ParacrossAction
......@@ -250,23 +266,29 @@ func setMinerTxResultFork(cfg *types.Chain33Config, status *pt.ParacrossNodeStat
}
}
//有tx且全部是user.p.x.paracross的commit tx时候设为0
//有tx且全部是user.p.x.paracross的commit tx时候是空块,发送时候需要等有实际交易时候再发
status.NonCommitTxCounts = 1
if len(curTxHashs) != 0 && len(curTxHashs) == len(isCommitTx) {
if len(allTxHashs) != 0 && len(allTxHashs) == len(isCommitTx) {
status.NonCommitTxCounts = 0
}
//主链自己过滤平行链tx, 对平行链执行失败的tx主链无法识别,主链和平行链需要获取相同的最初的tx map
//全部平行链tx结果
status.TxResult = []byte(hex.EncodeToString(util.CalcSingleBitMap(curTxHashs, receipts)))
clog.Debug("setMinerTxResultFork", "height", status.Height, "txResult", string(status.TxResult))
status.TxResult = []byte(hex.EncodeToString(util.CalcSingleBitMap(allTxHashs, receipts)))
//获取跨链资产转移交易信息
crossAssetTxHashs, err := FilterParaCrossAssetTxHashes(txs)
if err != nil {
return err
}
status.CrossTxResult = []byte(getCrossAssetTxBitMap(crossAssetTxHashs, allTxHashs, receipts))
//ForkLoopCheckCommitTxDone 后只保留全部txreseult 结果
if !pt.IsParaForkHeight(cfg, status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
//跨链tx结果
crossTxHashs := FilterParaCrossTxHashes(txs)
status.CrossTxResult = []byte(hex.EncodeToString(util.CalcBitMap(crossTxHashs, curTxHashs, receipts)))
status.TxHashs = [][]byte{CalcTxHashsHash(curTxHashs)}
status.CrossTxResult = []byte(hex.EncodeToString(util.CalcBitMap(crossTxHashs, allTxHashs, receipts)))
status.TxHashs = [][]byte{CalcTxHashsHash(allTxHashs)}
status.CrossTxHashs = [][]byte{CalcTxHashsHash(crossTxHashs)}
}
......
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package executor
import (
"fmt"
"math/big"
"testing"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
)
func TestGetCrossAssetTxBitMap(t *testing.T) {
var allTxs [][]byte
for i := 0; i < 6; i++ {
allTxs = append(allTxs, common.Sha256([]byte(fmt.Sprint(i))))
}
var crossTx [][]byte
hit := []int{0, 1, 2, 3}
for _, v := range hit {
crossTx = append(crossTx, common.Sha256([]byte(fmt.Sprint(v))))
}
d0 := &types.ReceiptData{Ty: types.ExecOk}
d1 := &types.ReceiptData{Ty: types.ExecPack}
d2 := &types.ReceiptData{Ty: types.ExecOk}
d3 := &types.ReceiptData{Ty: types.ExecErr}
d4 := &types.ReceiptData{Ty: types.ExecOk}
d5 := &types.ReceiptData{Ty: types.ExecOk}
receipts := []*types.ReceiptData{d0, d1, d2, d3, d4, d5}
rst := getCrossAssetTxBitMap(crossTx, allTxs, receipts)
assert.Equal(t, "000110101", rst)
//test nil
rst = getCrossAssetTxBitMap(nil, allTxs, receipts)
assert.Equal(t, "0001", rst)
//only one tx
cross2 := crossTx[:1]
rst = getCrossAssetTxBitMap(cross2, allTxs, receipts)
assert.Equal(t, "000111", rst)
//all cross fail
d0.Ty = types.ExecErr
d2.Ty = types.ExecErr
rst = getCrossAssetTxBitMap(crossTx, allTxs, receipts)
assert.Equal(t, "000110000", rst)
val := big.NewInt(0)
fmt.Println("v", val.Text(2))
}
......@@ -113,6 +113,28 @@ func FilterParaCrossTxHashes(txs []*types.Transaction) [][]byte {
return txHashs
}
// FilterParaCrossAssetTxHashes 只过滤跨链资产转移的类型
func FilterParaCrossAssetTxHashes(txs []*types.Transaction) ([][]byte, error) {
var txHashs [][]byte
for _, tx := range txs {
if types.IsParaExecName(string(tx.Execer)) && bytes.HasSuffix(tx.Execer, []byte(pt.ParaX)) {
var payload pt.ParacrossAction
err := types.Decode(tx.Payload, &payload)
if err != nil {
clog.Error("FilterParaCrossAssetTxHashes decode tx", "txhash", hex.EncodeToString(tx.Hash()), "err", err.Error())
return nil, err
}
if payload.Ty == pt.ParacrossActionAssetTransfer ||
payload.Ty == pt.ParacrossActionAssetWithdraw ||
payload.Ty >= pt.ParacrossActionCrossAssetTransfer {
txHashs = append(txHashs, tx.Hash())
}
}
}
return txHashs, nil
}
//经para filter之后, 交易组会存在如下几种tx:
// 1, 主链 paracross + 平行链 user.p.xx.paracross 跨链兑换合约
// 2, 主链 paracross + 平行链 user.p.xx.other 混合交易组合
......
......@@ -72,21 +72,33 @@ const (
//paraCrossTransferActionTypeEnd = 10100
)
//跨链转移类型是特别执行跨链资产转移的处理,在共识通过后,会做相应处理,其他类型都认为是普通paracross类型
//跨链资产转移的类型都放到paraCrossTransferActionTypeStart之后,方便管理
//这里NodeConfig,NodeGroupApply和SelfStageConfig虽然都是跨链类型,但是不算跨链资产转移,实际上不应该放这一类,历史版本就不修改了。
const (
// ParacrossActionAssetTransfer mainchain paracross asset transfer key
ParacrossActionAssetTransfer = iota + paraCrossTransferActionTypeStart
// ParacrossActionAssetWithdraw mainchain paracross asset withdraw key
ParacrossActionAssetWithdraw
//ParacrossActionNodeConfig para super node config
ParacrossActionNodeConfig
//ParacrossActionNodeGroupApply apply for node group initially
ParacrossActionNodeGroupApply
//ParacrossActionSelfStageConfig apply for self consensus stage config
ParacrossActionSelfStageConfig
// ParacrossActionCrossAssetTransfer crossChain asset transfer key
//注意: 此类型之后的一定也需要是跨链资产转移类型,方便代码计算,也就是在共识完成后,execCrossTx()处理到的类型。
ParacrossActionCrossAssetTransfer
)
//跨链共识交易crossResult bitmap版本,支持多版本的bitmap管理
const (
ParaCrossStatusBitMapVerLen = 4
ParaCrossStatusBitMapVer1 = "0001"
)
//paracross asset porcess
const (
ParacrossNoneTransfer = iota
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment