10 "github.com/vapor/account"
11 "github.com/vapor/blockchain/pseudohsm"
12 "github.com/vapor/blockchain/signers"
13 "github.com/vapor/blockchain/txbuilder"
14 "github.com/vapor/config"
15 "github.com/vapor/consensus"
16 "github.com/vapor/crypto/ed25519/chainkd"
17 "github.com/vapor/database"
18 "github.com/vapor/database/dbutils"
19 dbm "github.com/vapor/database/leveldb"
20 "github.com/vapor/database/storage"
21 "github.com/vapor/event"
22 "github.com/vapor/proposal"
23 "github.com/vapor/protocol"
24 "github.com/vapor/protocol/bc"
25 "github.com/vapor/protocol/bc/types"
26 "github.com/vapor/protocol/state"
29 func BenchmarkChain_CoinBaseTx_NoAsset(b *testing.B) {
30 benchInsertChain(b, 0, 0, "")
33 func BenchmarkChain_BtmTx_NoAsset_BASE(b *testing.B) {
34 benchInsertChain(b, 1, 0, "")
37 func BenchmarkChain_5000BtmTx_NoAsset_BASE(b *testing.B) {
38 benchInsertChain(b, 5000, 0, "")
41 func BenchmarkChain_5000BtmTx_1Asset_BASE(b *testing.B) {
42 benchInsertChain(b, 5000, 1, "")
45 // standard Transaction
46 func BenchmarkChain_BtmTx_NoAsset_P2PKH(b *testing.B) {
47 benchInsertChain(b, 1000, 0, "P2PKH")
50 func BenchmarkChain_BtmTx_1Asset_P2PKH(b *testing.B) {
51 benchInsertChain(b, 1000, 1, "P2PKH")
54 func BenchmarkChain_BtmTx_NoAsset_P2SH(b *testing.B) {
55 benchInsertChain(b, 100, 0, "P2SH")
58 func BenchmarkChain_BtmTx_1Asset_P2SH(b *testing.B) {
59 benchInsertChain(b, 100, 1, "P2SH")
62 func BenchmarkChain_BtmTx_NoAsset_MultiSign(b *testing.B) {
63 benchInsertChain(b, 100, 0, "MultiSign")
66 func BenchmarkChain_BtmTx_1Asset_MultiSign(b *testing.B) {
67 benchInsertChain(b, 100, 1, "MultiSign")
70 func benchInsertChain(b *testing.B, blockTxNumber int, otherAssetNum int, txType string) {
73 totalTxNumber := testNumber * blockTxNumber
75 dirPath, err := ioutil.TempDir(".", "testDB")
77 b.Fatal("create dirPath err:", err)
79 defer os.RemoveAll(dirPath)
81 testDB := dbm.NewDB("testdb", "leveldb", dirPath)
84 // Generate a chain test data.
85 chain, txs, txPool, err := GenerateChainData(dirPath, testDB, totalTxNumber, otherAssetNum, txType)
87 b.Fatal("GenerateChainData err:", err)
93 for i := 0; i < b.N; i++ {
94 testTxs := txs[blockTxNumber*i : blockTxNumber*(i+1)]
95 if err := InsertChain(chain, txPool, testTxs); err != nil {
96 b.Fatal("Failed to insert block into chain:", err)
101 func GenerateChainData(dirPath string, testDB dbutils.DB, txNumber, otherAssetNum int, txType string) (*protocol.Chain, []*types.Tx, *protocol.TxPool, error) {
104 // generate transactions
108 txs, err = MockTxsP2PKH(dirPath, testDB, txNumber, otherAssetNum)
110 return nil, nil, nil, err
113 txs, err = MockTxsP2SH(dirPath, testDB, txNumber, otherAssetNum)
115 return nil, nil, nil, err
118 txs, err = MockTxsMultiSign(dirPath, testDB, txNumber, otherAssetNum)
120 return nil, nil, nil, err
123 txs, err = CreateTxbyNum(txNumber, otherAssetNum)
125 return nil, nil, nil, err
129 // init UtxoViewpoint
130 utxoView := state.NewUtxoViewpoint()
131 utxoEntry := storage.NewUtxoEntry(storage.NormalUTXOType, 1, false)
132 for _, tx := range txs {
133 for _, id := range tx.SpentOutputIDs {
134 utxoView.Entries[id] = utxoEntry
138 if err := SetUtxoView(testDB, utxoView); err != nil {
139 return nil, nil, nil, err
142 config.CommonConfig = config.DefaultConfig()
143 store := database.NewStore(testDB)
144 dispatcher := event.NewDispatcher()
145 txPool := protocol.NewTxPool(store, dispatcher)
146 chain, err := protocol.NewChain(store, txPool, dispatcher)
148 return nil, nil, nil, err
151 go processNewTxch(txPool)
153 return chain, txs, txPool, nil
156 func InsertChain(chain *protocol.Chain, txPool *protocol.TxPool, txs []*types.Tx) error {
157 for _, tx := range txs {
158 if err := txbuilder.FinalizeTx(nil, chain, tx); err != nil {
163 block, err := proposal.NewBlockTemplate(chain, txPool, nil, uint64(time.Now().UnixNano()/1e6))
168 blockSize, err := block.MarshalText()
173 fmt.Println("blocksize:", uint64(len(blockSize)))
174 fmt.Println("block tx count:", uint64(len(block.Transactions)))
175 fmt.Println("coinbase txsize:", uint64(block.Transactions[0].SerializedSize))
176 if len(block.Transactions) > 1 {
177 fmt.Println("txsize:", uint64(block.Transactions[1].SerializedSize))
180 if _, err := chain.ProcessBlock(block); err != nil {
187 func processNewTxch(txPool *protocol.TxPool) {
190 func MockSimpleUtxo(index uint64, assetID *bc.AssetID, amount uint64, ctrlProg *account.CtrlProgram) *account.UTXO {
192 ctrlProg = &account.CtrlProgram{
196 ControlProgram: []byte{81},
201 utxo := &account.UTXO{
202 OutputID: bc.Hash{V0: 1},
203 SourceID: bc.Hash{V0: 1},
207 ControlProgram: ctrlProg.ControlProgram,
208 ControlProgramIndex: ctrlProg.KeyIndex,
209 AccountID: ctrlProg.AccountID,
210 Address: ctrlProg.Address,
217 func GenerateBaseUtxos(num int, amount uint64, ctrlProg *account.CtrlProgram) []*account.UTXO {
218 utxos := []*account.UTXO{}
219 for i := 0; i < num; i++ {
220 utxo := MockSimpleUtxo(uint64(i), consensus.BTMAssetID, amount, ctrlProg)
221 utxos = append(utxos, utxo)
227 func GenerateOtherUtxos(typeCount, num int, amount uint64, ctrlProg *account.CtrlProgram) []*account.UTXO {
228 utxos := []*account.UTXO{}
230 assetID := &bc.AssetID{
231 V0: uint64(typeCount),
237 for i := 0; i < num; i++ {
238 utxo := MockSimpleUtxo(uint64(typeCount*num+i), assetID, amount, ctrlProg)
239 utxos = append(utxos, utxo)
245 func AddTxInputFromUtxo(utxo *account.UTXO, singer *signers.Signer) (*types.TxInput, *txbuilder.SigningInstruction, error) {
246 txInput, signInst, err := account.UtxoToInputs(singer, utxo)
251 return txInput, signInst, nil
254 func AddTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *types.TxOutput {
255 out := types.NewIntraChainOutput(assetID, amount, controlProgram)
259 func CreateTxBuilder(baseUtxo *account.UTXO, btmServiceFlag bool, signer *signers.Signer) (*txbuilder.TemplateBuilder, error) {
260 tplBuilder := txbuilder.NewBuilder(time.Now())
263 txInput, signInst, err := AddTxInputFromUtxo(baseUtxo, signer)
267 tplBuilder.AddInput(txInput, signInst)
269 // if the btm is the service charge, didn't need to add the output
271 txOutput := AddTxOutput(baseUtxo.AssetID, 100, baseUtxo.ControlProgram)
272 tplBuilder.AddOutput(txOutput)
275 return tplBuilder, nil
278 func AddTxBuilder(tplBuilder *txbuilder.TemplateBuilder, utxo *account.UTXO, signer *signers.Signer) error {
279 txInput, signInst, err := AddTxInputFromUtxo(utxo, signer)
283 tplBuilder.AddInput(txInput, signInst)
285 txOutput := AddTxOutput(utxo.AssetID, utxo.Amount, utxo.ControlProgram)
286 tplBuilder.AddOutput(txOutput)
291 func BuildTx(baseUtxo *account.UTXO, otherUtxos []*account.UTXO, signer *signers.Signer) (*txbuilder.Template, error) {
292 btmServiceFlag := false
293 if otherUtxos == nil || len(otherUtxos) == 0 {
294 btmServiceFlag = true
297 tplBuilder, err := CreateTxBuilder(baseUtxo, btmServiceFlag, signer)
302 for _, u := range otherUtxos {
303 if err := AddTxBuilder(tplBuilder, u, signer); err != nil {
308 tpl, _, err := tplBuilder.Build()
316 func GenetrateTxbyUtxo(baseUtxo []*account.UTXO, otherUtxo [][]*account.UTXO) ([]*types.Tx, error) {
317 tmpUtxo := []*account.UTXO{}
319 otherUtxoFlag := true
321 if len(otherUtxo) == 0 || len(otherUtxo) != len(baseUtxo) {
322 otherUtxoFlag = false
325 for i := 0; i < len(baseUtxo); i++ {
327 tmpUtxo = otherUtxo[i]
332 tpl, err := BuildTx(baseUtxo[i], tmpUtxo, nil)
337 txs = append(txs, tpl.Transaction)
343 func CreateTxbyNum(txNumber, otherAssetNum int) ([]*types.Tx, error) {
344 baseUtxos := GenerateBaseUtxos(txNumber, 1000000000, nil)
345 otherUtxos := make([][]*account.UTXO, 0, txNumber)
346 if otherAssetNum != 0 {
347 for i := 0; i < txNumber; i++ {
348 utxos := GenerateOtherUtxos(i, otherAssetNum, 6000, nil)
349 otherUtxos = append(otherUtxos, utxos)
353 txs, err := GenetrateTxbyUtxo(baseUtxos, otherUtxos)
361 func SetUtxoView(db dbutils.DB, view *state.UtxoViewpoint) error {
362 batch := db.NewBatch()
363 if err := database.SaveUtxoView(batch, view); err != nil {
370 //-------------------------Mock actual transaction----------------------------------
371 func MockTxsP2PKH(keyDirPath string, testDB dbutils.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
372 accountManager := account.NewManager(testDB, nil)
373 hsm, err := pseudohsm.New(keyDirPath)
378 xpub, _, err := hsm.XCreate("TestP2PKH", "password", "en")
384 for i := 0; i < txNumber; i++ {
385 testAccountAlias := fmt.Sprintf("testAccount%d", i)
386 testAccount, err := accountManager.Create([]chainkd.XPub{xpub.XPub}, 1, testAccountAlias, signers.BIP0044)
391 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
396 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
397 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
398 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
403 if _, err := MockSign(tpl, hsm, "password"); err != nil {
407 txs = append(txs, tpl.Transaction)
413 func MockTxsP2SH(keyDirPath string, testDB dbutils.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
414 accountManager := account.NewManager(testDB, nil)
415 hsm, err := pseudohsm.New(keyDirPath)
420 xpub1, _, err := hsm.XCreate("TestP2SH1", "password", "en")
425 xpub2, _, err := hsm.XCreate("TestP2SH2", "password", "en")
431 for i := 0; i < txNumber; i++ {
432 testAccountAlias := fmt.Sprintf("testAccount%d", i)
433 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub, xpub2.XPub}, 2, testAccountAlias, signers.BIP0044)
438 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
443 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
444 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
445 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
450 if _, err := MockSign(tpl, hsm, "password"); err != nil {
454 txs = append(txs, tpl.Transaction)
460 func MockTxsMultiSign(keyDirPath string, testDB dbutils.DB, txNumber, otherAssetNum int) ([]*types.Tx, error) {
461 accountManager := account.NewManager(testDB, nil)
462 hsm, err := pseudohsm.New(keyDirPath)
467 xpub1, _, err := hsm.XCreate("TestMultilNodeSign1", "password1", "en")
472 xpub2, _, err := hsm.XCreate("TestMultilNodeSign2", "password2", "en")
477 for i := 0; i < txNumber; i++ {
478 testAccountAlias := fmt.Sprintf("testAccount%d", i)
479 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub, xpub2.XPub}, 2, testAccountAlias, signers.BIP0044)
484 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
489 utxo := MockSimpleUtxo(0, consensus.BTMAssetID, 1000000000, controlProg)
490 otherUtxos := GenerateOtherUtxos(i, otherAssetNum, 6000, controlProg)
491 tpl, err := BuildTx(utxo, otherUtxos, testAccount.Signer)
496 if _, err := MockSign(tpl, hsm, "password1"); err != nil {
500 if _, err := MockSign(tpl, hsm, "password2"); err != nil {
504 txs = append(txs, tpl.Transaction)