github.com/turingchain2020/turingchain@v1.1.21/blockchain/filter_paratx_test.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package blockchain_test
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/turingchain2020/turingchain/blockchain"
    15  	"github.com/turingchain2020/turingchain/client"
    16  	"github.com/turingchain2020/turingchain/common"
    17  	"github.com/turingchain2020/turingchain/common/crypto"
    18  	"github.com/turingchain2020/turingchain/common/merkle"
    19  	_ "github.com/turingchain2020/turingchain/system"
    20  	"github.com/turingchain2020/turingchain/types"
    21  	"github.com/turingchain2020/turingchain/util"
    22  	"github.com/turingchain2020/turingchain/util/testnode"
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  func addMainTx(cfg *types.TuringchainConfig, priv crypto.PrivKey, api client.QueueProtocolAPI) (string, error) {
    28  	txs := util.GenCoinsTxs(cfg, priv, 1)
    29  	hash := common.ToHex(txs[0].Hash())
    30  	reply, err := api.SendTx(txs[0])
    31  	if err != nil {
    32  		return hash, err
    33  	}
    34  	if !reply.GetIsOk() {
    35  		return hash, errors.New("sendtx unknow error")
    36  	}
    37  	return hash, nil
    38  }
    39  
    40  //构造单笔para交易
    41  func addSingleParaTx(cfg *types.TuringchainConfig, priv crypto.PrivKey, api client.QueueProtocolAPI, exec string) (string, error) {
    42  	tx := util.CreateTxWithExecer(cfg, priv, exec)
    43  	hash := common.ToHex(tx.Hash())
    44  	reply, err := api.SendTx(tx)
    45  	if err != nil {
    46  		return hash, err
    47  	}
    48  	if !reply.GetIsOk() {
    49  		return hash, errors.New("sendtx unknow error")
    50  	}
    51  	return hash, nil
    52  }
    53  
    54  //构造para交易组
    55  func addGroupParaTx(cfg *types.TuringchainConfig, priv crypto.PrivKey, api client.QueueProtocolAPI, title string, haveMainTx bool) (string, *types.ReplyStrings, error) {
    56  	var tx0 *types.Transaction
    57  	if haveMainTx {
    58  		tx0 = util.CreateTxWithExecer(cfg, priv, "coins")
    59  	} else {
    60  		tx0 = util.CreateTxWithExecer(cfg, priv, title+"coins")
    61  	}
    62  	tx1 := util.CreateTxWithExecer(cfg, priv, title+"token")
    63  	tx2 := util.CreateTxWithExecer(cfg, priv, title+"trade")
    64  	tx3 := util.CreateTxWithExecer(cfg, priv, title+"evm")
    65  	tx4 := util.CreateTxWithExecer(cfg, priv, title+"none")
    66  
    67  	var txs types.Transactions
    68  	txs.Txs = append(txs.Txs, tx0)
    69  	txs.Txs = append(txs.Txs, tx1)
    70  	txs.Txs = append(txs.Txs, tx2)
    71  	txs.Txs = append(txs.Txs, tx3)
    72  	txs.Txs = append(txs.Txs, tx4)
    73  	feeRate := cfg.GetMinTxFeeRate()
    74  	group, err := types.CreateTxGroup(txs.Txs, feeRate)
    75  	if err != nil {
    76  		chainlog.Error("addGroupParaTx", "err", err.Error())
    77  		return "", nil, err
    78  	}
    79  
    80  	var txHashs types.ReplyStrings
    81  	for i, tx := range group.Txs {
    82  		group.SignN(i, int32(types.SECP256K1), priv)
    83  		txhash := common.ToHex(tx.Hash())
    84  		txHashs.Datas = append(txHashs.Datas, txhash)
    85  
    86  	}
    87  
    88  	newtx := group.Tx()
    89  
    90  	hash := common.ToHex(newtx.Hash())
    91  	reply, err := api.SendTx(newtx)
    92  	if err != nil {
    93  		return "", nil, err
    94  	}
    95  	if !reply.GetIsOk() {
    96  		return "", nil, errors.New("sendtx unknow error")
    97  	}
    98  
    99  	return hash, &txHashs, nil
   100  }
   101  
   102  func TestGetParaTxByTitle(t *testing.T) {
   103  	//log.SetLogLevel("crit")
   104  	mock33 := testnode.New("", nil)
   105  	defer mock33.Close()
   106  	blockchain := mock33.GetBlockChain()
   107  	chainlog.Debug("TestGetParaTxByTitle begin --------------------")
   108  
   109  	//构造十个区块
   110  	curheight := blockchain.GetBlockHeight()
   111  	addblockheight := curheight + 10
   112  
   113  	_, err := blockchain.GetBlock(curheight)
   114  	if err != nil {
   115  		require.NoError(t, err)
   116  	}
   117  	cfg := mock33.GetClient().GetConfig()
   118  	for {
   119  		_, err = addMainTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI())
   120  		require.NoError(t, err)
   121  
   122  		_, err = addSingleParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.hyb.none")
   123  		require.NoError(t, err)
   124  
   125  		_, _, err = addGroupParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.hyb.", false)
   126  
   127  		require.NoError(t, err)
   128  
   129  		curheight = blockchain.GetBlockHeight()
   130  		_, err = blockchain.GetBlock(curheight)
   131  		require.NoError(t, err)
   132  		if curheight >= addblockheight {
   133  			break
   134  		}
   135  		time.Sleep(sendTxWait)
   136  	}
   137  	var req types.ReqParaTxByTitle
   138  	//通过seq获取para交易
   139  	req.Start = 0
   140  	req.End = curheight
   141  	req.Title = "user.p.hyb."
   142  	req.IsSeq = true
   143  	testgetParaTxByTitle(t, blockchain, &req, 0)
   144  
   145  	//通过height获取para交易
   146  	req.IsSeq = false
   147  	testgetParaTxByTitle(t, blockchain, &req, 0)
   148  
   149  	//通过height获取para交易,End大于当前最新高度报错
   150  	req.IsSeq = false
   151  	req.End = curheight + 10
   152  	testgetParaTxByTitle(t, blockchain, &req, 1)
   153  
   154  	curheight = blockchain.GetBlockHeight()
   155  	var height int64
   156  	for height = 0; height <= curheight; height++ {
   157  		testGetParaTxByHeight(cfg, t, blockchain, height)
   158  	}
   159  	//异常测试
   160  	req.Start = 3
   161  	req.End = 2
   162  	_, err = blockchain.GetParaTxByTitle(&req)
   163  	assert.Equal(t, err, types.ErrEndLessThanStartHeight)
   164  
   165  	req.Start = 1
   166  	req.End = 1
   167  	req.Title = "user.write"
   168  	_, err = blockchain.GetParaTxByTitle(&req)
   169  	assert.Equal(t, err, types.ErrInvalidParam)
   170  
   171  	//title 对应的交易不存在
   172  	req.Start = 1
   173  	req.End = 1
   174  	req.Title = "user.p.write"
   175  	paratxs, err := blockchain.GetParaTxByTitle(&req)
   176  	require.NoError(t, err)
   177  	assert.NotNil(t, paratxs)
   178  	for _, paratx := range paratxs.Items {
   179  		assert.Equal(t, types.AddBlock, paratx.Type)
   180  		assert.Nil(t, paratx.TxDetails)
   181  		assert.Nil(t, paratx.ChildHash)
   182  		assert.Nil(t, paratx.Proofs)
   183  		assert.Equal(t, uint32(0), paratx.Index)
   184  	}
   185  	chainlog.Debug("TestGetParaTxByTitle end --------------------")
   186  }
   187  func testgetParaTxByTitle(t *testing.T, blockchain *blockchain.BlockChain, req *types.ReqParaTxByTitle, flag int) {
   188  	count := req.End - req.Start + 1
   189  	ParaTxDetails, err := blockchain.GetParaTxByTitle(req)
   190  	if flag == 0 {
   191  		require.NoError(t, err)
   192  	}
   193  	if flag == 1 {
   194  		assert.Equal(t, err, types.ErrInvalidParam)
   195  		return
   196  	}
   197  	itemsLen := len(ParaTxDetails.Items)
   198  	assert.Equal(t, count, int64(itemsLen))
   199  
   200  	for i, txDetail := range ParaTxDetails.Items {
   201  		if txDetail != nil {
   202  			assert.Equal(t, txDetail.Header.Height, req.Start+int64(i))
   203  			//chainlog.Debug("testgetParaTxByTitle:", "Height", txDetail.Header.Height)
   204  			for _, tx := range txDetail.TxDetails {
   205  				if tx != nil {
   206  					execer := string(tx.Tx.Execer)
   207  					if !strings.HasPrefix(execer, "user.p.hyb.") && tx.Tx.GetGroupCount() != 0 {
   208  						//chainlog.Debug("testgetParaTxByTitle:maintxingroup", "tx", tx)
   209  						assert.Equal(t, tx.Receipt.Ty, int32(types.ExecOk))
   210  					} else {
   211  						assert.Equal(t, tx.Receipt.Ty, int32(types.ExecPack))
   212  					}
   213  					if tx.Proofs != nil {
   214  						roothash := merkle.GetMerkleRootFromBranch(tx.Proofs, tx.Tx.Hash(), tx.Index)
   215  						ok := bytes.Equal(roothash, txDetail.Header.GetHash())
   216  						assert.Equal(t, ok, false)
   217  					}
   218  				}
   219  			}
   220  		}
   221  	}
   222  }
   223  
   224  //获取当前高度上的所有平行链title
   225  func testGetParaTxByHeight(cfg *types.TuringchainConfig, t *testing.T, blockchain *blockchain.BlockChain, height int64) {
   226  
   227  	block, err := blockchain.GetBlock(height)
   228  	require.NoError(t, err)
   229  
   230  	_, err = blockchain.LoadParaTxByHeight(-1, "", 0, 1)
   231  	assert.Equal(t, types.ErrInvalidParam, err)
   232  
   233  	_, err = blockchain.LoadParaTxByHeight(height, "user.write", 0, 1)
   234  	assert.Equal(t, types.ErrInvalidParam, err)
   235  
   236  	replyparaTxs, err := blockchain.LoadParaTxByHeight(height, "", 0, 1)
   237  	if height == 0 {
   238  		return
   239  	}
   240  
   241  	require.NoError(t, err)
   242  	var mThreePhashes [][]byte
   243  	for _, paratx := range replyparaTxs.Items {
   244  		assert.Equal(t, paratx.Height, height)
   245  		assert.Equal(t, paratx.Hash, block.Block.Hash(cfg))
   246  		mThreePhashes = append(mThreePhashes, paratx.ChildHash)
   247  	}
   248  	//子roothash的proof证明
   249  	for _, childchain := range replyparaTxs.Items {
   250  		branch := merkle.GetMerkleBranch(mThreePhashes, childchain.GetChildHashIndex())
   251  		root := merkle.GetMerkleRootFromBranch(branch, childchain.ChildHash, childchain.GetChildHashIndex())
   252  		assert.Equal(t, block.Block.TxHash, root)
   253  	}
   254  	rootHash := merkle.GetMerkleRoot(mThreePhashes)
   255  	assert.Equal(t, block.Block.TxHash, rootHash)
   256  }
   257  func TestMultiLayerMerkleTree(t *testing.T) {
   258  	mock33 := testnode.New("", nil)
   259  	defer mock33.Close()
   260  	cfg := mock33.GetClient().GetConfig()
   261  	blockchain := mock33.GetBlockChain()
   262  	chainlog.Debug("TestMultiLayerMerkleTree begin --------------------")
   263  
   264  	//构造十个区块
   265  	curheight := blockchain.GetBlockHeight()
   266  	addblockheight := curheight + 10
   267  
   268  	_, err := blockchain.GetBlock(curheight)
   269  	if err != nil {
   270  		require.NoError(t, err)
   271  	}
   272  
   273  	for {
   274  		_, err = addMainTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI())
   275  		require.NoError(t, err)
   276  
   277  		_, err = addSingleParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.hyb.ticket")
   278  		require.NoError(t, err)
   279  		_, err = addSingleParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.test.coins")
   280  		require.NoError(t, err)
   281  		_, err = addSingleParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.para.game")
   282  		require.NoError(t, err)
   283  
   284  		_, _, err = addGroupParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.test.", false)
   285  		require.NoError(t, err)
   286  
   287  		_, _, err = addGroupParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.hyb.", false)
   288  		require.NoError(t, err)
   289  
   290  		_, _, err = addGroupParaTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI(), "user.p.para.", false)
   291  		require.NoError(t, err)
   292  		curheight = blockchain.GetBlockHeight()
   293  		_, err = blockchain.GetBlock(curheight)
   294  		require.NoError(t, err)
   295  		if curheight >= addblockheight {
   296  			break
   297  		}
   298  		time.Sleep(sendTxWait)
   299  	}
   300  
   301  	curheight = blockchain.GetBlockHeight()
   302  	var height int64
   303  	for height = 0; height <= curheight; height++ {
   304  		testParaTxByHeight(cfg, t, blockchain, height)
   305  	}
   306  	chainlog.Debug("TestMultiLayerMerkleTree end --------------------")
   307  }
   308  
   309  //获取当前高度上的所有平行链title
   310  func testParaTxByHeight(cfg *types.TuringchainConfig, t *testing.T, blockchain *blockchain.BlockChain, height int64) {
   311  
   312  	block, err := blockchain.GetBlock(height)
   313  	require.NoError(t, err)
   314  	merkleroothash := block.Block.GetTxHash()
   315  
   316  	blockheight := block.Block.GetHeight()
   317  	if cfg.IsPara() {
   318  		blockheight = block.Block.GetMainHeight()
   319  	}
   320  
   321  	for txindex, tx := range block.Block.Txs {
   322  		txProof, err := blockchain.ProcQueryTxMsg(tx.Hash())
   323  		require.NoError(t, err)
   324  		txhash := tx.Hash()
   325  		if cfg.IsFork(blockheight, "ForkRootHash") {
   326  			txhash = tx.FullHash()
   327  		}
   328  
   329  		//证明txproof的正确性,
   330  		if txProof.GetProofs() != nil { //ForkRootHash 之前的proof证明
   331  			brroothash := merkle.GetMerkleRootFromBranch(txProof.GetProofs(), txhash, uint32(txindex))
   332  			assert.Equal(t, merkleroothash, brroothash)
   333  		} else if txProof.GetTxProofs() != nil { //ForkRootHash 之后的proof证明
   334  			var childhash []byte
   335  			for i, txproof := range txProof.GetTxProofs() {
   336  				if i == 0 {
   337  					childhash = merkle.GetMerkleRootFromBranch(txproof.GetProofs(), txhash, txproof.GetIndex())
   338  					if txproof.GetRootHash() != nil {
   339  						assert.Equal(t, txproof.GetRootHash(), childhash)
   340  					} else {
   341  						assert.Equal(t, txproof.GetIndex(), uint32(txindex))
   342  						assert.Equal(t, merkleroothash, childhash)
   343  					}
   344  				} else {
   345  					brroothash := merkle.GetMerkleRootFromBranch(txproof.GetProofs(), childhash, txproof.GetIndex())
   346  					assert.Equal(t, merkleroothash, brroothash)
   347  				}
   348  			}
   349  		}
   350  	}
   351  }