github.com/turingchain2020/turingchain@v1.1.21/executor/executor_real_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 executor_test 6 7 import ( 8 "errors" 9 "fmt" 10 "net/http" 11 _ "net/http/pprof" 12 "testing" 13 14 "sync" 15 16 "github.com/turingchain2020/turingchain/common" 17 "github.com/turingchain2020/turingchain/common/address" 18 "github.com/turingchain2020/turingchain/common/merkle" 19 _ "github.com/turingchain2020/turingchain/system" 20 drivers "github.com/turingchain2020/turingchain/system/dapp" 21 "github.com/turingchain2020/turingchain/types" 22 "github.com/turingchain2020/turingchain/util" 23 "github.com/turingchain2020/turingchain/util/testnode" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 var runonce sync.Once 28 29 func init() { 30 types.AllowUserExec = append(types.AllowUserExec, []byte("demo2")) 31 go func() { 32 http.ListenAndServe("localhost:6060", nil) 33 }() 34 } 35 36 func TestExecGenesisBlock(t *testing.T) { 37 mock33 := newMockNode() 38 defer mock33.Close() 39 mock33.WaitHeight(0) 40 block := mock33.GetBlock(0) 41 assert.Equal(t, block.Height, int64(0)) 42 } 43 44 func newMockNode() *testnode.TuringchainMock { 45 cfg := testnode.GetDefaultConfig() 46 cfg.GetModuleConfig().Consensus.Minerstart = false 47 runonce.Do(func() { 48 drivers.Register(cfg, "demo2", newdemoApp, 1) 49 }) 50 mock33 := testnode.NewWithConfig(cfg, nil) 51 return mock33 52 } 53 54 func TestTxGroup(t *testing.T) { 55 mock33 := newMockNode() 56 defer mock33.Close() 57 cfg := mock33.GetClient().GetConfig() 58 prev := cfg.GetMinTxFeeRate() 59 cfg.SetMinFee(100000) 60 defer cfg.SetMinFee(prev) 61 mcfg := mock33.GetCfg() 62 genkey := mock33.GetGenesisKey() 63 mock33.WaitHeight(0) 64 block := mock33.GetBlock(0) 65 acc := mock33.GetAccount(block.StateHash, mcfg.Consensus.Genesis) 66 assert.Equal(t, acc.Balance, 100000000*types.Coin) 67 var txs []*types.Transaction 68 addr2, priv2 := util.Genaddress() 69 addr3, priv3 := util.Genaddress() 70 addr4, _ := util.Genaddress() 71 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr2, types.Coin)) 72 txs = append(txs, util.CreateCoinsTx(cfg, priv2, addr3, types.Coin)) 73 txs = append(txs, util.CreateCoinsTx(cfg, priv3, addr4, types.Coin)) 74 //执行三笔交易: 全部正确 75 feeRate := cfg.GetMinTxFeeRate() 76 txgroup, err := types.CreateTxGroup(txs, feeRate) 77 assert.Nil(t, err) 78 //重新签名 79 txgroup.SignN(0, types.SECP256K1, genkey) 80 txgroup.SignN(1, types.SECP256K1, priv2) 81 txgroup.SignN(2, types.SECP256K1, priv3) 82 //返回新的区块 83 block, err = util.ExecAndCheckBlock(mock33.GetClient(), block, txgroup.GetTxs(), []int{types.ExecOk, types.ExecOk, types.ExecOk}) 84 assert.Nil(t, err) 85 assert.Equal(t, mock33.GetAccount(block.StateHash, mock33.GetGenesisAddress()).Balance, int64(9999999899700000)) 86 assert.Equal(t, mock33.GetAccount(block.StateHash, addr2).Balance, int64(0)) 87 assert.Equal(t, mock33.GetAccount(block.StateHash, addr3).Balance, int64(0)) 88 assert.Equal(t, mock33.GetAccount(block.StateHash, addr4).Balance, 1*types.Coin) 89 90 //执行三笔交易:第一比错误 91 txs = nil 92 txs = append(txs, util.CreateCoinsTx(cfg, priv2, addr3, 2*types.Coin)) 93 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr4, types.Coin)) 94 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr4, types.Coin)) 95 96 txgroup, err = types.CreateTxGroup(txs, feeRate) 97 assert.Nil(t, err) 98 //重新签名 99 txgroup.SignN(0, types.SECP256K1, priv2) 100 txgroup.SignN(1, types.SECP256K1, genkey) 101 txgroup.SignN(2, types.SECP256K1, genkey) 102 103 _, err = util.ExecAndCheckBlock(mock33.GetClient(), block, txgroup.GetTxs(), []int{types.ExecErr, types.ExecErr, types.ExecErr}) 104 assert.Nil(t, err) 105 //执行三笔交易:第二比错误 106 txs = nil 107 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr2, types.Coin)) 108 txs = append(txs, util.CreateCoinsTx(cfg, priv2, addr4, 2*types.Coin)) 109 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr4, types.Coin)) 110 111 txgroup, err = types.CreateTxGroup(txs, feeRate) 112 assert.Nil(t, err) 113 //重新签名 114 txgroup.SignN(0, types.SECP256K1, genkey) 115 txgroup.SignN(1, types.SECP256K1, priv2) 116 txgroup.SignN(2, types.SECP256K1, genkey) 117 118 _, err = util.ExecAndCheckBlock(mock33.GetClient(), block, txgroup.GetTxs(), []int{types.ExecPack, types.ExecPack, types.ExecPack}) 119 assert.Nil(t, err) 120 //执行三笔交易: 第三比错误 121 txs = nil 122 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr2, types.Coin)) 123 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr4, types.Coin)) 124 txs = append(txs, util.CreateCoinsTx(cfg, priv2, addr4, 10*types.Coin)) 125 126 txgroup, err = types.CreateTxGroup(txs, feeRate) 127 assert.Nil(t, err) 128 //重新签名 129 txgroup.SignN(0, types.SECP256K1, genkey) 130 txgroup.SignN(1, types.SECP256K1, genkey) 131 txgroup.SignN(2, types.SECP256K1, priv2) 132 133 _, err = util.ExecAndCheckBlock(mock33.GetClient(), block, txgroup.GetTxs(), []int{types.ExecPack, types.ExecPack, types.ExecPack}) 134 assert.Nil(t, err) 135 //执行三笔交易:其中有一笔是user.xxx的执行器 136 txs = nil 137 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr2, types.Coin)) 138 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr4, types.Coin)) 139 txs = append(txs, util.CreateCoinsTx(cfg, priv2, addr4, 10*types.Coin)) 140 txs[2].Execer = []byte("user.xxx") 141 txs[2].To = address.ExecAddress("user.xxx") 142 txgroup, err = types.CreateTxGroup(txs, feeRate) 143 assert.Nil(t, err) 144 //重新签名 145 txgroup.SignN(0, types.SECP256K1, genkey) 146 txgroup.SignN(1, types.SECP256K1, genkey) 147 txgroup.SignN(2, types.SECP256K1, priv2) 148 149 _, err = util.ExecAndCheckBlock(mock33.GetClient(), block, txgroup.GetTxs(), []int{2, 2, 1}) 150 assert.Nil(t, err) 151 } 152 153 func TestExecAllow(t *testing.T) { 154 mock33 := newMockNode() 155 defer mock33.Close() 156 cfg := mock33.GetClient().GetConfig() 157 prev := cfg.GetMinTxFeeRate() 158 cfg.SetMinFee(100000) 159 defer cfg.SetMinFee(prev) 160 genkey := mock33.GetGenesisKey() 161 genaddr := mock33.GetGenesisAddress() 162 mock33.WaitHeight(0) 163 block := mock33.GetBlock(0) 164 tx1 := util.CreateTxWithExecer(cfg, genkey, "user.evm") //allow 165 tx2 := util.CreateTxWithExecer(cfg, genkey, "coins") //allow 166 tx3 := util.CreateTxWithExecer(cfg, genkey, "evmxx") //not allow 167 tx4 := util.CreateTxWithExecer(cfg, genkey, "user.evmxx.xxx") //allow 168 assert.Equal(t, mock33.GetAccount(block.StateHash, genaddr).Balance, 100000000*types.Coin) 169 txs := []*types.Transaction{tx1, tx2, tx3, tx4} 170 var err error 171 block, err = util.ExecAndCheckBlockCB(mock33.GetClient(), block, txs, func(index int, receipt *types.ReceiptData) error { 172 if index == 0 && receipt.GetTy() != 1 { 173 return errors.New("user.evm is allow") 174 } 175 if index == 1 && receipt.GetTy() != 2 { 176 return errors.New("coins exec ok") 177 } 178 if index == 2 && receipt != nil { 179 return errors.New("evmxx is not allow") 180 } 181 if index == 3 && receipt.GetTy() != 1 { 182 return errors.New("user.evmxx.xxx is allow") 183 } 184 return nil 185 }) 186 assert.Nil(t, err) 187 } 188 189 func TestExecBlock2(t *testing.T) { 190 mock33 := newMockNode() 191 defer mock33.Close() 192 cfg := mock33.GetClient().GetConfig() 193 genkey := mock33.GetGenesisKey() 194 genaddr := mock33.GetGenesisAddress() 195 mock33.WaitHeight(0) 196 block := mock33.GetBlock(0) 197 assert.Equal(t, mock33.GetAccount(block.StateHash, genaddr).Balance, 100000000*types.Coin) 198 txs := util.GenCoinsTxs(cfg, genkey, 2) 199 200 block2 := util.CreateNewBlock(cfg, block, txs) 201 detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false) 202 if err != nil { 203 t.Error(err) 204 return 205 } 206 for _, Receipt := range detail.Receipts { 207 if Receipt.GetTy() != 2 { 208 t.Errorf("exec expect true, but now false") 209 } 210 } 211 212 N := 1000 213 done := make(chan struct{}, N) 214 for i := 0; i < N; i++ { 215 go func() { 216 txs := util.GenCoinsTxs(cfg, genkey, 2) 217 block3 := util.CreateNewBlock(cfg, block2, txs) 218 detail, _, err := util.ExecBlock(mock33.GetClient(), block2.StateHash, block3, false, true, false) 219 assert.Nil(t, err) 220 for _, Receipt := range detail.Receipts { 221 if Receipt.GetTy() != 2 { 222 t.Errorf("exec expect true, but now false") 223 } 224 } 225 done <- struct{}{} 226 }() 227 } 228 for n := 0; n < N; n++ { 229 <-done 230 } 231 } 232 233 var zeroHash [32]byte 234 235 func TestSameTx(t *testing.T) { 236 mock33 := newMockNode() 237 defer mock33.Close() 238 cfg := mock33.GetClient().GetConfig() 239 newblock := &types.Block{} 240 newblock.Height = 1 241 newblock.BlockTime = types.Now().Unix() 242 newblock.ParentHash = zeroHash[:] 243 newblock.Txs = util.GenNoneTxs(cfg, mock33.GetGenesisKey(), 3) 244 hash1 := merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs) 245 newblock.Txs = append(newblock.Txs, newblock.Txs[2]) 246 newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs) 247 assert.Equal(t, hash1, newblock.TxHash) 248 _, _, err := util.ExecBlock(mock33.GetClient(), nil, newblock, true, true, false) 249 assert.Equal(t, types.ErrTxDup, err) 250 251 //情况2 252 //[tx1,xt2,tx3,tx4,tx5,tx6] and [tx1,xt2,tx3,tx4,tx5,tx6,tx5,tx6] 253 newblock.Txs = util.GenNoneTxs(cfg, mock33.GetGenesisKey(), 6) 254 hash1 = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs) 255 newblock.Txs = append(newblock.Txs, newblock.Txs[4:]...) 256 newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs) 257 assert.Equal(t, hash1, newblock.TxHash) 258 _, _, err = util.ExecBlock(mock33.GetClient(), nil, newblock, true, true, false) 259 assert.Equal(t, types.ErrTxDup, err) 260 } 261 262 func TestExecBlock(t *testing.T) { 263 mock33 := newMockNode() 264 defer mock33.Close() 265 cfg := mock33.GetClient().GetConfig() 266 mock33.WaitHeight(0) 267 block0 := mock33.GetBlock(0) 268 block := util.CreateCoinsBlock(cfg, mock33.GetGenesisKey(), 10) 269 util.ExecBlock(mock33.GetClient(), block0.StateHash, block, false, true, false) 270 } 271 272 //区块执行性能更好的一个测试 273 //1. 先生成 10万个账户,每个账户转1000个币 274 //2. 每个区块随机取1万比交易,然后执行 275 //3. 执行1000个块,看性能曲线的变化 276 //4. 排除掉网络掉影响 277 //5. 先对leveldb 做一个性能的测试 278 279 //区块执行新能测试 280 func BenchmarkExecBlock(b *testing.B) { 281 b.ReportAllocs() 282 mock33 := newMockNode() 283 defer mock33.Close() 284 cfg := mock33.GetClient().GetConfig() 285 block := util.CreateCoinsBlock(cfg, mock33.GetGenesisKey(), 10000) 286 mock33.WaitHeight(0) 287 block0 := mock33.GetBlock(0) 288 account := mock33.GetAccount(block0.StateHash, mock33.GetGenesisAddress()) 289 assert.Equal(b, int64(10000000000000000), account.Balance) 290 b.ResetTimer() 291 for i := 0; i < b.N; i++ { 292 util.ExecBlock(mock33.GetClient(), block0.StateHash, block, false, true, false) 293 } 294 } 295 296 /* 297 ExecLocalSameTime test 298 */ 299 type demoApp struct { 300 *drivers.DriverBase 301 } 302 303 func newdemoApp() drivers.Driver { 304 demo := &demoApp{DriverBase: &drivers.DriverBase{}} 305 demo.SetChild(demo) 306 return demo 307 } 308 309 func (demo *demoApp) GetDriverName() string { 310 return "demo2" 311 } 312 313 var orderflag = drivers.ExecLocalSameTime 314 315 func (demo *demoApp) ExecutorOrder() int64 { 316 return orderflag 317 } 318 319 func (demo *demoApp) Exec(tx *types.Transaction, index int) (receipt *types.Receipt, err error) { 320 addr := tx.From() 321 id := common.ToHex(tx.Hash()) 322 values, err := demo.GetLocalDB().List(demoCalcLocalKey(addr, ""), nil, 0, 0) 323 if err != nil && err != types.ErrNotFound { 324 return nil, err 325 } 326 if seterrkey { 327 println("set err key value") 328 err = demo.GetLocalDB().Set([]byte("key1"), []byte("value1")) 329 if err != nil { 330 return nil, err 331 } 332 } 333 receipt = &types.Receipt{Ty: types.ExecOk} 334 receipt.KV = append(receipt.KV, &types.KeyValue{ 335 Key: demoCalcStateKey(addr, id), 336 Value: []byte(fmt.Sprint(len(values))), 337 }) 338 k := []byte("LODB-demo2-localkey") 339 data, err := demo.GetLocalDB().Get(k) 340 if err != nil && err != types.ErrNotFound { 341 return nil, err 342 } 343 count := &types.Int64{Data: 0} 344 if err == nil { 345 err = types.Decode(data, count) 346 if err != nil { 347 return nil, err 348 } 349 } 350 count.Data++ 351 receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: int32(len(values)), 352 Log: types.Encode(count)}) 353 return receipt, nil 354 } 355 356 func (demo *demoApp) ExecLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (localkv *types.LocalDBSet, err error) { 357 localkv = &types.LocalDBSet{} 358 var count types.Int64 359 err = types.Decode(receipt.Logs[0].Log, &count) 360 if err != nil { 361 return nil, err 362 } 363 localkv.KV = append(localkv.KV, &types.KeyValue{ 364 Key: []byte("LODB-demo2-localkey"), 365 Value: receipt.Logs[0].Log, 366 }) 367 localkv.KV = append(localkv.KV, &types.KeyValue{ 368 Key: []byte("LODB-demo2-localkey" + fmt.Sprint(count.GetData())), 369 Value: receipt.Logs[0].Log, 370 }) 371 if count.GetData() > 0 { 372 localkv.KV = append(localkv.KV, &types.KeyValue{ 373 Key: []byte("LODB-demo2-localkey" + fmt.Sprint(count.GetData()-1)), 374 Value: nil, 375 }) 376 } 377 return localkv, nil 378 } 379 380 func demoCalcStateKey(addr string, id string) []byte { 381 key := append([]byte("mavl-demo2-"), []byte(addr)...) 382 key = append(key, []byte(":")...) 383 key = append(key, []byte(id)...) 384 return key 385 } 386 387 func demoCalcLocalKey(addr string, id string) []byte { 388 key := append([]byte("LODB-demo2-"), []byte(addr)...) 389 key = append(key, []byte(":")...) 390 if len(id) > 0 { 391 key = append(key, []byte(id)...) 392 } 393 return key 394 } 395 396 func TestExecLocalSameTime1(t *testing.T) { 397 mock33 := newMockNode() 398 defer mock33.Close() 399 cfg := mock33.GetClient().GetConfig() 400 orderflag = 1 401 genkey := mock33.GetGenesisKey() 402 genaddr := mock33.GetGenesisAddress() 403 mock33.WaitHeight(0) 404 block := mock33.GetBlock(0) 405 assert.Equal(t, mock33.GetAccount(block.StateHash, genaddr).Balance, 100000000*types.Coin) 406 var txs []*types.Transaction 407 addr1, priv1 := util.Genaddress() 408 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr1, 1e8)) 409 txs = append(txs, util.CreateTxWithExecer(cfg, priv1, "demo2")) 410 txs = append(txs, util.CreateTxWithExecer(cfg, priv1, "demo2")) 411 block2 := util.CreateNewBlock(cfg, block, txs) 412 detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false) 413 if err != nil { 414 t.Error(err) 415 return 416 } 417 for i, receipt := range detail.Receipts { 418 assert.Equal(t, receipt.GetTy(), int32(2), fmt.Sprint(i)) 419 } 420 receipt1 := detail.Receipts[1] 421 assert.Equal(t, receipt1.Logs[1].Log, types.Encode(&types.Int64{Data: 1})) 422 receipt2 := detail.Receipts[2] 423 assert.Equal(t, receipt2.Logs[1].Log, types.Encode(&types.Int64{Data: 2})) 424 } 425 426 func TestExecLocalSameTime0(t *testing.T) { 427 mock33 := newMockNode() 428 defer mock33.Close() 429 cfg := mock33.GetClient().GetConfig() 430 orderflag = 0 431 genkey := mock33.GetGenesisKey() 432 genaddr := mock33.GetGenesisAddress() 433 mock33.WaitHeight(0) 434 block := mock33.GetBlock(0) 435 assert.Equal(t, mock33.GetAccount(block.StateHash, genaddr).Balance, 100000000*types.Coin) 436 var txs []*types.Transaction 437 addr1, priv1 := util.Genaddress() 438 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr1, 1e8)) 439 txs = append(txs, util.CreateTxWithExecer(cfg, priv1, "demo2")) 440 txs = append(txs, util.CreateTxWithExecer(cfg, priv1, "demo2")) 441 block2 := util.CreateNewBlock(cfg, block, txs) 442 detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false) 443 if err != nil { 444 t.Error(err) 445 return 446 } 447 assert.Equal(t, detail.Receipts[0].GetTy(), int32(2)) 448 receipt1 := detail.Receipts[1] 449 assert.Equal(t, receipt1.Logs[1].Log, []byte(types.ErrDisableRead.Error())) 450 receipt2 := detail.Receipts[2] 451 assert.Equal(t, receipt2.Logs[1].Log, []byte(types.ErrDisableRead.Error())) 452 } 453 454 var seterrkey = false 455 456 func TestExecLocalSameTimeSetErrKey(t *testing.T) { 457 mock33 := newMockNode() 458 defer mock33.Close() 459 cfg := mock33.GetClient().GetConfig() 460 orderflag = 1 461 seterrkey = true 462 genkey := mock33.GetGenesisKey() 463 genaddr := mock33.GetGenesisAddress() 464 mock33.WaitHeight(0) 465 block := mock33.GetBlock(0) 466 assert.Equal(t, mock33.GetAccount(block.StateHash, genaddr).Balance, 100000000*types.Coin) 467 var txs []*types.Transaction 468 addr1, priv1 := util.Genaddress() 469 txs = append(txs, util.CreateCoinsTx(cfg, genkey, addr1, 1e8)) 470 txs = append(txs, util.CreateTxWithExecer(cfg, priv1, "demo2")) 471 txs = append(txs, util.CreateTxWithExecer(cfg, priv1, "demo2")) 472 block2 := util.CreateNewBlock(cfg, block, txs) 473 detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false) 474 if err != nil { 475 t.Error(err) 476 return 477 } 478 for i, receipt := range detail.Receipts { 479 if i == 0 { 480 assert.Equal(t, receipt.GetTy(), int32(2)) 481 } 482 if i >= 1 { 483 assert.Equal(t, receipt.GetTy(), int32(1)) 484 assert.Equal(t, len(receipt.Logs), 2) 485 assert.Equal(t, receipt.Logs[1].Ty, int32(1)) 486 } 487 } 488 }