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 }