10 dbm "github.com/tendermint/tmlibs/db"
12 "github.com/vapor/account"
13 "github.com/vapor/blockchain/pseudohsm"
14 "github.com/vapor/blockchain/signers"
15 "github.com/vapor/blockchain/txbuilder"
16 "github.com/vapor/config"
17 "github.com/vapor/consensus"
18 engine "github.com/vapor/consensus/consensus"
19 "github.com/vapor/consensus/consensus/dpos"
20 "github.com/vapor/crypto/ed25519/chainkd"
21 "github.com/vapor/database/leveldb"
22 "github.com/vapor/database/storage"
23 "github.com/vapor/mining"
24 "github.com/vapor/protocol"
25 "github.com/vapor/protocol/bc"
26 "github.com/vapor/protocol/bc/types"
27 "github.com/vapor/protocol/state"
30 func BenchmarkChain_CoinBaseTx_NoAsset(b *testing.B) {
31 benchInsertChain(b, 0, 0, "")
34 func BenchmarkChain_BtmTx_NoAsset_BASE(b *testing.B) {
35 benchInsertChain(b, 1, 0, "")
38 func BenchmarkChain_5000BtmTx_NoAsset_BASE(b *testing.B) {
39 benchInsertChain(b, 5000, 0, "")
42 func BenchmarkChain_5000BtmTx_1Asset_BASE(b *testing.B) {
43 benchInsertChain(b, 5000, 1, "")
46 // standard Transaction
47 func BenchmarkChain_BtmTx_NoAsset_P2PKH(b *testing.B) {
48 benchInsertChain(b, 1000, 0, "P2PKH")
51 func BenchmarkChain_BtmTx_1Asset_P2PKH(b *testing.B) {
52 benchInsertChain(b, 1000, 1, "P2PKH")
55 func BenchmarkChain_BtmTx_NoAsset_P2SH(b *testing.B) {
56 benchInsertChain(b, 100, 0, "P2SH")
59 func BenchmarkChain_BtmTx_1Asset_P2SH(b *testing.B) {
60 benchInsertChain(b, 100, 1, "P2SH")
63 func BenchmarkChain_BtmTx_NoAsset_MultiSign(b *testing.B) {
64 benchInsertChain(b, 100, 0, "MultiSign")
67 func BenchmarkChain_BtmTx_1Asset_MultiSign(b *testing.B) {
68 benchInsertChain(b, 100, 1, "MultiSign")
71 func benchInsertChain(b *testing.B, blockTxNumber int, otherAssetNum int, txType string) {
74 totalTxNumber := testNumber * blockTxNumber
76 dirPath, err := ioutil.TempDir(".", "testDB")
78 b.Fatal("create dirPath err:", err)
80 defer os.RemoveAll(dirPath)
82 testDB := dbm.NewDB("testdb", "leveldb", dirPath)
85 // Generate a chain test data.
86 chain, txs, txPool, err := GenerateChainData(dirPath, testDB, totalTxNumber, otherAssetNum, txType)
88 b.Fatal("GenerateChainData err:", err)
94 for i := 0; i < b.N; i++ {
95 testTxs := txs[blockTxNumber*i : blockTxNumber*(i+1)]
96 if err := InsertChain(chain, txPool, testTxs); err != nil {
97 b.Fatal("Failed to insert block into chain:", err)
102 func GenerateChainData(dirPath string, testDB dbm.DB, txNumber, otherAssetNum int, txType string) (*protocol.Chain, []*types.Tx, *protocol.TxPool, error) {
105 // generate transactions
109 txs, err = MockTxsP2PKH(dirPath, testDB, txNumber, otherAssetNum)
111 return nil, nil, nil, err
114 txs, err = MockTxsP2SH(dirPath, testDB, txNumber, otherAssetNum)
116 return nil, nil, nil, err
119 txs, err = MockTxsMultiSign(dirPath, testDB, txNumber, otherAssetNum)
121 return nil, nil, nil, err
124 txs, err = CreateTxbyNum(txNumber, otherAssetNum)
126 return nil, nil, nil, err
130 // init UtxoViewpoint
131 utxoView := state.NewUtxoViewpoint()
132 utxoEntry := storage.NewUtxoEntry(false, 1, false)
133 for _, tx := range txs {
134 for _, id := range tx.SpentOutputIDs {
135 utxoView.Entries[id] = utxoEntry
139 if err := SetUtxoView(testDB, utxoView); err != nil {
140 return nil, nil, nil, err
142 var engine engine.Engine
143 switch config.CommonConfig.Consensus.Type {
148 store := leveldb.NewStore(testDB)
149 txPool := protocol.NewTxPool(store)
150 chain, err := protocol.NewChain(store, txPool, engine)
152 return nil, nil, nil, err
155 go processNewTxch(txPool)
157 return chain, txs, txPool, nil
160 func InsertChain(chain *protocol.Chain, txPool *protocol.TxPool, txs []*types.Tx) error {
161 for _, tx := range txs {
162 if err := txbuilder.FinalizeTx(nil, chain, tx); err != nil {
167 block, err := mining.NewBlockTemplate(chain, txPool, nil, nil, nil)
172 blockSize, err := block.MarshalText()
177 fmt.Println("blocksize:", uint64(len(blockSize)))
178 fmt.Println("block tx count:", uint64(len(block.Transactions)))
179 fmt.Println("coinbase txsize:", uint64(block.Transactions[0].SerializedSize))
180 if len(block.Transactions) > 1 {
181 fmt.Println("txsize:", uint64(block.Transactions[1].SerializedSize))
184 if _, err := chain.ProcessBlock(block); err != nil {
191 func processNewTxch(txPool *protocol.TxPool) {
192 newTxCh := txPool.GetMsgCh()
193 for tx := range newTxCh {
199 func MockSimpleUtxo(index uint64, assetID *bc.AssetID, amount uint64, ctrlProg *account.CtrlProgram) *account.UTXO {
201 ctrlProg = &account.CtrlProgram{
205 ControlProgram: []byte{81},
210 utxo := &account.UTXO{
211 OutputID: bc.Hash{V0: 1},
212 SourceID: bc.Hash{V0: 1},
216 ControlProgram: ctrlProg.ControlProgram,
217 ControlProgramIndex: ctrlProg.KeyIndex,
218 AccountID: ctrlProg.AccountID,
219 Address: ctrlProg.Address,
226 func GenerateBaseUtxos(num int, amount uint64, ctrlProg *account.CtrlProgram) []*account.UTXO {
227 utxos := []*account.UTXO{}
228 for i := 0; i < num; i++ {
229 utxo := MockSimpleUtxo(uint64(i), consensus.BTMAssetID, amount, ctrlProg)
230 utxos = append(utxos, utxo)
236 func GenerateOtherUtxos(typeCount, num int, amount uint64, ctrlProg *account.CtrlProgram) []*account.UTXO {
237 utxos := []*account.UTXO{}
239 assetID := &bc.AssetID{
240 V0: uint64(typeCount),
246 for i := 0; i < num; i++ {
247 utxo := MockSimpleUtxo(uint64(typeCount*num+i), assetID, amount, ctrlProg)
248 utxos = append(utxos, utxo)
254 func AddTxInputFromUtxo(utxo *account.UTXO, singer *signers.Signer) (*types.TxInput, *txbuilder.SigningInstruction, error) {
255 txInput, signInst, err := account.UtxoToInputs(singer, utxo)
260 return txInput, signInst, nil
263 func AddTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *types.TxOutput {
264 out := types.NewTxOutput(assetID, amount, controlProgram)
268 func CreateTxBuilder(baseUtxo *account.UTXO, btmServiceFlag bool, signer *signers.Signer) (*txbuilder.TemplateBuilder, error) {
269 tplBuilder := txbuilder.NewBuilder(time.Now())
272 txInput, signInst, err := AddTxInputFromUtxo(baseUtxo, signer)
276 tplBuilder.AddInput(txInput, signInst)
278 // if the btm is the service charge, didn't need to add the output
280 txOutput := AddTxOutput(baseUtxo.AssetID, 100, baseUtxo.ControlProgram)
281 tplBuilder.AddOutput(txOutput)
284 return tplBuilder, nil
287 func AddTxBuilder(tplBuilder *txbuilder.TemplateBuilder, utxo *account.UTXO, signer *signers.Signer) error {
288 txInput, signInst, err := AddTxInputFromUtxo(utxo, signer)
292 tplBuilder.AddInput(txInput, signInst)
294 txOutput := AddTxOutput(utxo.AssetID, utxo.Amount, utxo.ControlProgram)
295 tplBuilder.AddOutput(txOutput)
300 func BuildTx(baseUtxo *account.UTXO, otherUtxos []*account.UTXO, signer *signers.Signer) (*txbuilder.Template, error) {
301 btmServiceFlag := false
302 if otherUtxos == nil || len(otherUtxos) == 0 {
303 btmServiceFlag = true
306 tplBuilder, err := CreateTxBuilder(baseUtxo, btmServiceFlag, signer)
311 for _, u := range otherUtxos {
312 if err := AddTxBuilder(tplBuilder, u, signer); err != nil {
317 tpl, _, err := tplBuilder.Build()
325 func GenetrateTxbyUtxo(baseUtxo []*account.UTXO, otherUtxo [][]*account.UTXO) ([]*types.Tx, error) {
326 tmpUtxo := []*account.UTXO{}
328 otherUtxoFlag := true
330 if len(otherUtxo) == 0 || len(otherUtxo) != len(baseUtxo) {
331 otherUtxoFlag = false
334 for i := 0; i < len(baseUtxo); i++ {
336 tmpUtxo = otherUtxo[i]
341 tpl, err := BuildTx(baseUtxo[i], tmpUtxo, nil)
346 txs = append(txs, tpl.Transaction)
352 func CreateTxbyNum(txNumber, otherAssetNum int) ([]*types.Tx, error) {
353 baseUtxos := GenerateBaseUtxos(txNumber, 1000000000, nil)
354 otherUtxos := make([][]*account.UTXO, 0, txNumber)
355 if otherAssetNum != 0 {
356 for i := 0; i < txNumber; i++ {
357 utxos := GenerateOtherUtxos(i, otherAssetNum, 6000, nil)
358 otherUtxos = append(otherUtxos, utxos)
362 txs, err := GenetrateTxbyUtxo(baseUtxos, otherUtxos)
370 func SetUtxoView(db dbm.DB, view *state.UtxoViewpoint) error {
371 batch := db.NewBatch()
372 if err := leveldb.SaveUtxoView(batch, view); err != nil {
379 //-------------------------Mock actual transaction----------------------------------
380 func MockTxsP2PKH(keyDirPath string, testDB dbm.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
381 accountManager := account.NewManager(testDB, nil)
382 hsm, err := pseudohsm.New(keyDirPath)
387 xpub, _, err := hsm.XCreate("TestP2PKH", "password", "en")
393 for i := 0; i < txNumber; i++ {
394 testAccountAlias := fmt.Sprintf("testAccount%d", i)
395 testAccount, err := accountManager.Create([]chainkd.XPub{xpub.XPub}, 1, testAccountAlias, signers.BIP0044)
400 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
405 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
406 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
407 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
412 if _, err := MockSign(tpl, hsm, "password"); err != nil {
416 txs = append(txs, tpl.Transaction)
422 func MockTxsP2SH(keyDirPath string, testDB dbm.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
423 accountManager := account.NewManager(testDB, nil)
424 hsm, err := pseudohsm.New(keyDirPath)
429 xpub1, _, err := hsm.XCreate("TestP2SH1", "password", "en")
434 xpub2, _, err := hsm.XCreate("TestP2SH2", "password", "en")
440 for i := 0; i < txNumber; i++ {
441 testAccountAlias := fmt.Sprintf("testAccount%d", i)
442 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub, xpub2.XPub}, 2, testAccountAlias, signers.BIP0044)
447 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
452 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
453 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
454 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
459 if _, err := MockSign(tpl, hsm, "password"); err != nil {
463 txs = append(txs, tpl.Transaction)
469 func MockTxsMultiSign(keyDirPath string, testDB dbm.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
470 accountManager := account.NewManager(testDB, nil)
471 hsm, err := pseudohsm.New(keyDirPath)
476 xpub1, _, err := hsm.XCreate("TestMultilNodeSign1", "password1", "en")
481 xpub2, _, err := hsm.XCreate("TestMultilNodeSign2", "password2", "en")
486 for i := 0; i < txNumber; i++ {
487 testAccountAlias := fmt.Sprintf("testAccount%d", i)
488 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub, xpub2.XPub}, 2, testAccountAlias, signers.BIP0044)
493 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
498 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
499 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
500 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
505 if _, err := MockSign(tpl, hsm, "password1"); err != nil {
509 if _, err := MockSign(tpl, hsm, "password2"); err != nil {
513 txs = append(txs, tpl.Transaction)