10 dbm "github.com/tendermint/tmlibs/db"
12 "github.com/bytom/account"
13 "github.com/bytom/blockchain/pseudohsm"
14 "github.com/bytom/blockchain/signers"
15 "github.com/bytom/blockchain/txbuilder"
16 "github.com/bytom/consensus"
17 "github.com/bytom/consensus/difficulty"
18 "github.com/bytom/crypto/ed25519/chainkd"
19 "github.com/bytom/database/leveldb"
20 "github.com/bytom/database/storage"
21 "github.com/bytom/mining"
22 "github.com/bytom/protocol"
23 "github.com/bytom/protocol/bc"
24 "github.com/bytom/protocol/bc/types"
25 "github.com/bytom/protocol/state"
28 func BenchmarkChain_CoinBaseTx_NoAsset(b *testing.B) {
29 benchInsertChain(b, 0, 0, "")
32 func BenchmarkChain_BtmTx_NoAsset_BASE(b *testing.B) {
33 benchInsertChain(b, 1, 0, "")
36 func BenchmarkChain_5000BtmTx_NoAsset_BASE(b *testing.B) {
37 benchInsertChain(b, 5000, 0, "")
40 func BenchmarkChain_5000BtmTx_1Asset_BASE(b *testing.B) {
41 benchInsertChain(b, 5000, 1, "")
44 // standard Transaction
45 func BenchmarkChain_BtmTx_NoAsset_P2PKH(b *testing.B) {
46 benchInsertChain(b, 1000, 0, "P2PKH")
49 func BenchmarkChain_BtmTx_1Asset_P2PKH(b *testing.B) {
50 benchInsertChain(b, 1000, 1, "P2PKH")
53 func BenchmarkChain_BtmTx_NoAsset_P2SH(b *testing.B) {
54 benchInsertChain(b, 100, 0, "P2SH")
57 func BenchmarkChain_BtmTx_1Asset_P2SH(b *testing.B) {
58 benchInsertChain(b, 100, 1, "P2SH")
61 func BenchmarkChain_BtmTx_NoAsset_MultiSign(b *testing.B) {
62 benchInsertChain(b, 100, 0, "MultiSign")
65 func BenchmarkChain_BtmTx_1Asset_MultiSign(b *testing.B) {
66 benchInsertChain(b, 100, 1, "MultiSign")
69 func benchInsertChain(b *testing.B, blockTxNumber int, otherAssetNum int, txType string) {
72 totalTxNumber := testNumber * blockTxNumber
74 dirPath, err := ioutil.TempDir(".", "testDB")
76 b.Fatal("create dirPath err:", err)
78 defer os.RemoveAll(dirPath)
80 testDB := dbm.NewDB("testdb", "leveldb", dirPath)
83 // Generate a chain test data.
84 chain, txs, txPool, err := GenerateChainData(dirPath, testDB, totalTxNumber, otherAssetNum, txType)
86 b.Fatal("GenerateChainData err:", err)
92 for i := 0; i < b.N; i++ {
93 testTxs := txs[blockTxNumber*i : blockTxNumber*(i+1)]
94 if err := InsertChain(chain, txPool, testTxs); err != nil {
95 b.Fatal("Failed to insert block into chain:", err)
100 func GenerateChainData(dirPath string, testDB dbm.DB, txNumber, otherAssetNum int, txType string) (*protocol.Chain, []*types.Tx, *protocol.TxPool, error) {
103 // generate transactions
107 txs, err = MockTxsP2PKH(dirPath, testDB, txNumber, otherAssetNum)
109 return nil, nil, nil, err
112 txs, err = MockTxsP2SH(dirPath, testDB, txNumber, otherAssetNum)
114 return nil, nil, nil, err
117 txs, err = MockTxsMultiSign(dirPath, testDB, txNumber, otherAssetNum)
119 return nil, nil, nil, err
122 txs, err = CreateTxbyNum(txNumber, otherAssetNum)
124 return nil, nil, nil, err
128 // init UtxoViewpoint
129 utxoView := state.NewUtxoViewpoint()
130 utxoEntry := storage.NewUtxoEntry(false, 1, false)
131 for _, tx := range txs {
132 for _, id := range tx.SpentOutputIDs {
133 utxoView.Entries[id] = utxoEntry
137 if err := SetUtxoView(testDB, utxoView); err != nil {
138 return nil, nil, nil, err
141 txPool := protocol.NewTxPool()
142 store := leveldb.NewStore(testDB)
143 chain, err := protocol.NewChain(store, txPool)
145 return nil, nil, nil, err
148 go processNewTxch(txPool)
150 return chain, txs, txPool, nil
153 func InsertChain(chain *protocol.Chain, txPool *protocol.TxPool, txs []*types.Tx) error {
154 for _, tx := range txs {
155 if err := txbuilder.FinalizeTx(nil, chain, tx); err != nil {
160 block, err := mining.NewBlockTemplate(chain, txPool, nil)
165 blockSize, err := block.MarshalText()
170 fmt.Println("blocksize:", uint64(len(blockSize)))
171 fmt.Println("block tx count:", uint64(len(block.Transactions)))
172 fmt.Println("coinbase txsize:", uint64(block.Transactions[0].SerializedSize))
173 if len(block.Transactions) > 1 {
174 fmt.Println("txsize:", uint64(block.Transactions[1].SerializedSize))
177 seed, err := chain.CalcNextSeed(&block.PreviousBlockHash)
182 if err := SolveBlock(seed, block); err != nil {
186 if _, err := chain.ProcessBlock(block); err != nil {
193 func processNewTxch(txPool *protocol.TxPool) {
194 newTxCh := txPool.GetMsgCh()
195 for tx := range newTxCh {
201 func SolveBlock(seed *bc.Hash, block *types.Block) error {
202 maxNonce := ^uint64(0) // 2^64 - 1
203 header := &block.BlockHeader
204 for i := uint64(0); i < maxNonce; i++ {
206 headerHash := header.Hash()
207 if difficulty.CheckProofOfWork(&headerHash, seed, header.Bits) {
214 func MockSimpleUtxo(index uint64, assetID *bc.AssetID, amount uint64, ctrlProg *account.CtrlProgram) *account.UTXO {
216 ctrlProg = &account.CtrlProgram{
220 ControlProgram: []byte{81},
225 utxo := &account.UTXO{
226 OutputID: bc.Hash{V0: 1},
227 SourceID: bc.Hash{V0: 1},
231 ControlProgram: ctrlProg.ControlProgram,
232 ControlProgramIndex: ctrlProg.KeyIndex,
233 AccountID: ctrlProg.AccountID,
234 Address: ctrlProg.Address,
241 func GenerateBaseUtxos(num int, amount uint64, ctrlProg *account.CtrlProgram) []*account.UTXO {
242 utxos := []*account.UTXO{}
243 for i := 0; i < num; i++ {
244 utxo := MockSimpleUtxo(uint64(i), consensus.BTMAssetID, amount, ctrlProg)
245 utxos = append(utxos, utxo)
251 func GenerateOtherUtxos(typeCount, num int, amount uint64, ctrlProg *account.CtrlProgram) []*account.UTXO {
252 utxos := []*account.UTXO{}
254 assetID := &bc.AssetID{
255 V0: uint64(typeCount),
261 for i := 0; i < num; i++ {
262 utxo := MockSimpleUtxo(uint64(typeCount*num+i), assetID, amount, ctrlProg)
263 utxos = append(utxos, utxo)
269 func AddTxInputFromUtxo(utxo *account.UTXO, singer *signers.Signer) (*types.TxInput, *txbuilder.SigningInstruction, error) {
270 txInput, signInst, err := account.UtxoToInputs(singer, utxo)
275 return txInput, signInst, nil
278 func AddTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *types.TxOutput {
279 out := types.NewTxOutput(assetID, amount, controlProgram)
283 func CreateTxBuilder(baseUtxo *account.UTXO, btmServiceFlag bool, signer *signers.Signer) (*txbuilder.TemplateBuilder, error) {
284 tplBuilder := txbuilder.NewBuilder(time.Now())
287 txInput, signInst, err := AddTxInputFromUtxo(baseUtxo, signer)
291 tplBuilder.AddInput(txInput, signInst)
293 // if the btm is the service charge, didn't need to add the output
295 txOutput := AddTxOutput(baseUtxo.AssetID, 100, baseUtxo.ControlProgram)
296 tplBuilder.AddOutput(txOutput)
299 return tplBuilder, nil
302 func AddTxBuilder(tplBuilder *txbuilder.TemplateBuilder, utxo *account.UTXO, signer *signers.Signer) error {
303 txInput, signInst, err := AddTxInputFromUtxo(utxo, signer)
307 tplBuilder.AddInput(txInput, signInst)
309 txOutput := AddTxOutput(utxo.AssetID, utxo.Amount, utxo.ControlProgram)
310 tplBuilder.AddOutput(txOutput)
315 func BuildTx(baseUtxo *account.UTXO, otherUtxos []*account.UTXO, signer *signers.Signer) (*txbuilder.Template, error) {
316 btmServiceFlag := false
317 if otherUtxos == nil || len(otherUtxos) == 0 {
318 btmServiceFlag = true
321 tplBuilder, err := CreateTxBuilder(baseUtxo, btmServiceFlag, signer)
326 for _, u := range otherUtxos {
327 if err := AddTxBuilder(tplBuilder, u, signer); err != nil {
332 tpl, _, err := tplBuilder.Build()
340 func GenetrateTxbyUtxo(baseUtxo []*account.UTXO, otherUtxo [][]*account.UTXO) ([]*types.Tx, error) {
341 tmpUtxo := []*account.UTXO{}
343 otherUtxoFlag := true
345 if len(otherUtxo) == 0 || len(otherUtxo) != len(baseUtxo) {
346 otherUtxoFlag = false
349 for i := 0; i < len(baseUtxo); i++ {
351 tmpUtxo = otherUtxo[i]
356 tpl, err := BuildTx(baseUtxo[i], tmpUtxo, nil)
361 txs = append(txs, tpl.Transaction)
367 func CreateTxbyNum(txNumber, otherAssetNum int) ([]*types.Tx, error) {
368 baseUtxos := GenerateBaseUtxos(txNumber, 1000000000, nil)
369 otherUtxos := make([][]*account.UTXO, 0, txNumber)
370 if otherAssetNum != 0 {
371 for i := 0; i < txNumber; i++ {
372 utxos := GenerateOtherUtxos(i, otherAssetNum, 6000, nil)
373 otherUtxos = append(otherUtxos, utxos)
377 txs, err := GenetrateTxbyUtxo(baseUtxos, otherUtxos)
385 func SetUtxoView(db dbm.DB, view *state.UtxoViewpoint) error {
386 batch := db.NewBatch()
387 if err := leveldb.SaveUtxoView(batch, view); err != nil {
394 //-------------------------Mock actual transaction----------------------------------
395 func MockTxsP2PKH(keyDirPath string, testDB dbm.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
396 accountManager := account.NewManager(testDB, nil)
397 hsm, err := pseudohsm.New(keyDirPath)
402 xpub, err := hsm.XCreate("TestP2PKH", "password")
408 for i := 0; i < txNumber; i++ {
409 testAccountAlias := fmt.Sprintf("testAccount%d", i)
410 testAccount, err := accountManager.Create([]chainkd.XPub{xpub.XPub}, 1, testAccountAlias)
415 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
420 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
421 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
422 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
427 if _, err := MockSign(tpl, hsm, "password"); err != nil {
431 txs = append(txs, tpl.Transaction)
437 func MockTxsP2SH(keyDirPath string, testDB dbm.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
438 accountManager := account.NewManager(testDB, nil)
439 hsm, err := pseudohsm.New(keyDirPath)
444 xpub1, err := hsm.XCreate("TestP2SH1", "password")
449 xpub2, err := hsm.XCreate("TestP2SH2", "password")
455 for i := 0; i < txNumber; i++ {
456 testAccountAlias := fmt.Sprintf("testAccount%d", i)
457 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub, xpub2.XPub}, 2, testAccountAlias)
462 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
467 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
468 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
469 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
474 if _, err := MockSign(tpl, hsm, "password"); err != nil {
478 txs = append(txs, tpl.Transaction)
484 func MockTxsMultiSign(keyDirPath string, testDB dbm.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
485 accountManager := account.NewManager(testDB, nil)
486 hsm, err := pseudohsm.New(keyDirPath)
491 xpub1, err := hsm.XCreate("TestMultilNodeSign1", "password1")
496 xpub2, err := hsm.XCreate("TestMultilNodeSign2", "password2")
501 for i := 0; i < txNumber; i++ {
502 testAccountAlias := fmt.Sprintf("testAccount%d", i)
503 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub, xpub2.XPub}, 2, testAccountAlias)
508 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
513 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
514 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
515 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
520 if _, err := MockSign(tpl, hsm, "password1"); err != nil {
524 if _, err := MockSign(tpl, hsm, "password2"); err != nil {
528 txs = append(txs, tpl.Transaction)