Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 37e88a7

Browse files
aakselrodtuxcanfly
authored andcommittedMay 22, 2015
Use generate instead of setgenerate RPC
1 parent 118af08 commit 37e88a7

File tree

6 files changed

+136
-175
lines changed

6 files changed

+136
-175
lines changed
 

‎actor.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ type TxOut struct {
6565
// NewActor creates a new actor which runs its own wallet process connecting
6666
// to the btcd node server specified by node, and listening for simulator
6767
// websocket connections on the specified port.
68-
func NewActor(node *Node, port uint16) (*Actor, error) {
68+
func NewActor(port uint16) (*Actor, error) {
6969
// Please don't run this as root.
7070
if port < 1024 {
7171
return nil, errors.New("invalid actor port")
7272
}
7373

7474
// Set btcwallet node args
75-
args, err := newBtcwalletArgs(port, node.Args.(*btcdArgs))
75+
args, err := newBtcwalletArgs(port)
7676
if err != nil {
7777
return nil, err
7878
}

‎btcwallet.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,13 @@ type btcwalletArgs struct {
5050
}
5151

5252
// newBtcwalletArgs returns a btcwalletArgs with all default values
53-
func newBtcwalletArgs(port uint16, nodeArgs *btcdArgs) (*btcwalletArgs, error) {
53+
func newBtcwalletArgs(port uint16) (*btcwalletArgs, error) {
5454
a := &btcwalletArgs{
55-
RPCListen: fmt.Sprintf("127.0.0.1:%d", port),
56-
RPCConnect: "127.0.0.1:18556",
57-
Username: "user",
58-
Password: "pass",
59-
Certificates: nodeArgs.certificates,
60-
CAFile: CertFile,
55+
RPCListen: fmt.Sprintf("127.0.0.1:%d", port),
56+
RPCConnect: "127.0.0.1:18556",
57+
Username: "user",
58+
Password: "pass",
59+
CAFile: CertFile,
6160

6261
prefix: fmt.Sprintf("actor-%d", port),
6362
exe: "btcwallet",
@@ -83,6 +82,11 @@ func (a *btcwalletArgs) SetDefaults() error {
8382
return err
8483
}
8584
a.LogDir = logdir
85+
certs, err := ioutil.ReadFile(CertFile)
86+
if err != nil {
87+
return err
88+
}
89+
a.Certificates = certs
8690
return nil
8791
}
8892

‎btcwallet_test.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ import (
2222
)
2323

2424
func TestnewBtcwalletArgs(t *testing.T) {
25-
btcdArgs, err := newBtcdArgs("node")
26-
args, err := newBtcwalletArgs(18554, btcdArgs)
27-
defer btcdArgs.Cleanup()
25+
args, err := newBtcwalletArgs(18554)
2826
defer args.Cleanup()
2927
if err != nil {
3028
t.Errorf("newBtcwalletArgs error: %v", err)

‎comm.go

+116-138
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ func (com *Communication) Start(actors []*Actor, node *Node, txCurve map[int32]*
162162
com.wg.Add(1)
163163
go com.Shutdown(miner, actors, node)
164164

165+
log.Printf("%s: Generating %v blocks...", miner, *startBlock)
166+
if err := miner.Generate(uint32(*startBlock) - 1); err != nil {
167+
return
168+
}
169+
165170
return
166171
}
167172

@@ -428,159 +433,132 @@ func (com *Communication) estimateTpb(tpbChan chan<- int) {
428433
func (com *Communication) Communicate(txCurve map[int32]*Row, miner *Miner, actors []*Actor) {
429434
defer com.wg.Done()
430435

431-
for {
436+
for h, row := range txCurve {
437+
// wait until this block is processed
432438
select {
433-
case h := <-com.height:
434-
435-
// stop simulation if we're at the last block
436-
if h > int32(*stopBlock) {
437-
close(com.exit)
438-
return
439-
}
440-
441-
// disable mining until the required no. of tx are in mempool
442-
if err := miner.StopMining(); err != nil {
443-
close(com.exit)
444-
return
445-
}
446-
447-
// wait until this block is processed
448-
select {
449-
case <-com.blockQueue.processed:
450-
case <-com.exit:
451-
return
452-
}
453-
454-
var wg sync.WaitGroup
455-
// count the number of utxos available in total
456-
var utxoCount int
457-
for _, a := range actors {
458-
utxoCount += len(a.utxoQueue.utxos)
459-
}
439+
case <-com.blockQueue.processed:
440+
case <-com.exit:
441+
return
442+
}
460443

461-
// the required transactions are divided into two groups because we need some of them to
462-
// contribute to the utxo count required for the next block and the rest to contribute to
463-
// the tx count
464-
//
465-
// it is possible to keep dividing the same utxo until it's broken into the required
466-
// number of pieces but we want to stay close to the real world scenario and maximize
467-
// the number of utxos used
468-
//
469-
// E.g: Assume the following CSV
470-
//
471-
// block,utxos,tx
472-
// 20000,40000,20000
473-
// 20001,50000,25000
474-
//
475-
// at block 19999, we need to ensure that next block has 40K utxos
476-
// we have 19999 - blockchain.CoinbaseMaturity = 19899 utxos
477-
// we need to create 40K-19899 = 20101 utxos so in this case, so
478-
// we create 20101 tx which give 1 net utxo output
479-
//
480-
// at block 20000, we need to ensure that next block has 50K utxos
481-
// we already have 40K by the previous iteration, so we need 50-40 = 10K utxos
482-
// we also need to generate 20K tx before the next block, so
483-
// create 10000 tx which generate 1 net utxo plus 10000 tx without any net utxo
484-
//
485-
// since we cannot generate more tx than the no of available utxos, the no of tx
486-
// that can be generated at any iteration is limited by the utxos available
487-
488-
// in case the next row doesn't exist, we initialize the required no of utxos to zero
489-
// so we keep the utxoCount same as current count
490-
next, ok := txCurve[h+2]
491-
if !ok {
492-
next = &Row{}
493-
next.utxoCount = utxoCount
494-
}
444+
var wg sync.WaitGroup
445+
// count the number of utxos available in total
446+
var utxoCount int
447+
for _, a := range actors {
448+
utxoCount += len(a.utxoQueue.utxos)
449+
}
495450

496-
// reqUtxoCount is the number of utxos required
497-
reqUtxoCount := 0
498-
if next.utxoCount > utxoCount {
499-
reqUtxoCount = next.utxoCount - utxoCount
500-
}
451+
// the required transactions are divided into two groups because we need some of them to
452+
// contribute to the utxo count required for the next block and the rest to contribute to
453+
// the tx count
454+
//
455+
// it is possible to keep dividing the same utxo until it's broken into the required
456+
// number of pieces but we want to stay close to the real world scenario and maximize
457+
// the number of utxos used
458+
//
459+
// E.g: Assume the following CSV
460+
//
461+
// block,utxos,tx
462+
// 20000,40000,20000
463+
// 20001,50000,25000
464+
//
465+
// at block 19999, we need to ensure that next block has 40K utxos
466+
// we have 19999 - blockchain.CoinbaseMaturity = 19899 utxos
467+
// we need to create 40K-19899 = 20101 utxos so in this case, so
468+
// we create 20101 tx which give 1 net utxo output
469+
//
470+
// at block 20000, we need to ensure that next block has 50K utxos
471+
// we already have 40K by the previous iteration, so we need 50-40 = 10K utxos
472+
// we also need to generate 20K tx before the next block, so
473+
// create 10000 tx which generate 1 net utxo plus 10000 tx without any net utxo
474+
//
475+
// since we cannot generate more tx than the no of available utxos, the no of tx
476+
// that can be generated at any iteration is limited by the utxos available
477+
478+
// in case the next row doesn't exist, we initialize the required no of utxos to zero
479+
// so we keep the utxoCount same as current count
480+
next, ok := txCurve[h+1]
481+
if !ok {
482+
next = &Row{}
483+
next.utxoCount = utxoCount
484+
}
501485

502-
// in case this row doesn't exist, we initialize the required no of tx to reqUtxoCount
503-
// i.e one tx per utxo required
504-
row, ok := txCurve[h+1]
505-
if !ok {
506-
row = &Row{}
507-
row.txCount = reqUtxoCount
508-
}
486+
// reqUtxoCount is the number of utxos required
487+
reqUtxoCount := 0
488+
if next.utxoCount > utxoCount {
489+
reqUtxoCount = next.utxoCount - utxoCount
490+
}
509491

510-
// reqTxCount is the number of tx that will generate reqUtxoCount
511-
// no of utxos
512-
reqTxCount := row.txCount
513-
if reqTxCount > utxoCount {
514-
log.Printf("Warning: capping no of transactions at %v based on no of available utxos", utxoCount)
515-
// cap the total no of tx at the no of available utxos
516-
reqTxCount = utxoCount
517-
}
492+
// reqTxCount is the number of tx that will generate reqUtxoCount
493+
// no of utxos
494+
reqTxCount := row.txCount
495+
if reqTxCount > utxoCount {
496+
log.Printf("Warning: capping no of transactions at %v based on no of available utxos", utxoCount)
497+
// cap the total no of tx at the no of available utxos
498+
reqTxCount = utxoCount
499+
}
518500

519-
var multiplier, totalUtxos, totalTx int
520-
// skip if we already have more than the no of utxos required
521-
if reqUtxoCount > 0 {
522-
// e.g: if we need 18K utxos in 12K tx
523-
// multiplier = [18000/12000] = [1.5] = 2
524-
// totalUtxos = 18000/2 = 9000
525-
// totalTx = 120000 - 9000 = 3000
526-
multiplier = int(math.Ceil(float64(reqUtxoCount) / float64(reqTxCount)))
527-
if multiplier > *maxSplit {
528-
// cap maximum splits at maxSplit
529-
multiplier = *maxSplit
530-
}
531-
totalUtxos = reqUtxoCount / multiplier
501+
var multiplier, totalUtxos, totalTx int
502+
// skip if we already have more than the no of utxos required
503+
if reqUtxoCount > 0 {
504+
// e.g: if we need 18K utxos in 12K tx
505+
// multiplier = [18000/12000] = [1.5] = 2
506+
// totalUtxos = 18000/2 = 9000
507+
// totalTx = 120000 - 9000 = 3000
508+
multiplier = int(math.Ceil(float64(reqUtxoCount) / float64(reqTxCount)))
509+
if multiplier > *maxSplit {
510+
// cap maximum splits at maxSplit
511+
multiplier = *maxSplit
532512
}
513+
totalUtxos = reqUtxoCount / multiplier
514+
}
533515

534-
// if we're not already covered by the utxo transactions, generate additional tx
535-
if reqTxCount > totalUtxos {
536-
totalTx = reqTxCount - totalUtxos
537-
}
516+
// if we're not already covered by the utxo transactions, generate additional tx
517+
if reqTxCount > totalUtxos {
518+
totalTx = reqTxCount - totalUtxos
519+
}
538520

539-
if reqTxCount > 0 {
540-
log.Printf("Generating %v transactions ...", reqTxCount)
541-
}
542-
if totalTx > 0 {
543-
for i := 0; i < totalTx; i++ {
544-
fmt.Printf("\r%d/%d", i+1, reqTxCount)
545-
a := actors[rand.Int()%len(actors)]
546-
addr := a.ownedAddresses[rand.Int()%len(a.ownedAddresses)]
547-
select {
548-
case com.downstream <- addr:
549-
// For every address sent downstream (one transaction about to happen),
550-
// spawn a goroutine to listen for an accepted transaction in the mempool
551-
wg.Add(1)
552-
go com.txPoolRecv(&wg)
553-
case <-com.exit:
554-
return
555-
}
521+
if reqTxCount > 0 {
522+
log.Printf("Generating %v transactions ...", reqTxCount)
523+
}
524+
if totalTx > 0 {
525+
for i := 0; i < totalTx; i++ {
526+
fmt.Printf("\r%d/%d", i+1, reqTxCount)
527+
a := actors[rand.Int()%len(actors)]
528+
addr := a.ownedAddresses[rand.Int()%len(a.ownedAddresses)]
529+
select {
530+
case com.downstream <- addr:
531+
// For every address sent downstream (one transaction about to happen),
532+
// spawn a goroutine to listen for an accepted transaction in the mempool
533+
wg.Add(1)
534+
go com.txPoolRecv(&wg)
535+
case <-com.exit:
536+
return
556537
}
557538
}
539+
}
558540

559-
if totalUtxos > 0 {
560-
for i := 0; i < totalUtxos; i++ {
561-
fmt.Printf("\r%d/%d", i+totalTx+1, reqTxCount)
562-
select {
563-
case com.split <- multiplier:
564-
// For every address sent downstream (one transaction about to happen),
565-
// spawn a goroutine to listen for an accepted transaction in the mempool
566-
wg.Add(1)
567-
go com.txPoolRecv(&wg)
568-
case <-com.exit:
569-
return
570-
}
541+
if totalUtxos > 0 {
542+
for i := 0; i < totalUtxos; i++ {
543+
fmt.Printf("\r%d/%d", i+totalTx+1, reqTxCount)
544+
select {
545+
case com.split <- multiplier:
546+
// For every address sent downstream (one transaction about to happen),
547+
// spawn a goroutine to listen for an accepted transaction in the mempool
548+
wg.Add(1)
549+
go com.txPoolRecv(&wg)
550+
case <-com.exit:
551+
return
571552
}
572553
}
554+
}
573555

574-
fmt.Printf("\n")
575-
log.Printf("Waiting for miner...")
576-
wg.Wait()
577-
// mine the above tx in the next block
578-
if err := miner.StartMining(); err != nil {
579-
close(com.exit)
580-
return
581-
}
582-
case <-com.exit:
583-
return
556+
fmt.Printf("\n")
557+
log.Printf("Waiting for miner...")
558+
wg.Wait()
559+
// mine the above tx in the next block
560+
if err := miner.Generate(1); err != nil {
561+
close(com.exit)
584562
}
585563
}
586564
}

‎miner.go

+5-24
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,7 @@ func NewMiner(miningAddrs []btcutil.Address, exit chan struct{},
4141
// send a signal to stop actors. This is used so main can break from
4242
// select and call actor.Stop to stop actors.
4343
OnBlockConnected: func(hash *wire.ShaHash, h int32) {
44-
if h >= int32(*startBlock)-1 {
45-
if height != nil {
46-
height <- h
47-
}
48-
} else {
44+
if h <= int32(*startBlock) {
4945
fmt.Printf("\r%d/%d", h, *startBlock)
5046
}
5147
},
@@ -107,34 +103,19 @@ func NewMiner(miningAddrs []btcutil.Address, exit chan struct{},
107103
return miner, err
108104
}
109105

110-
// Use just one core for mining.
111-
if err := miner.StartMining(); err != nil {
112-
return miner, err
113-
}
114-
115106
// Register for block notifications.
116107
if err := miner.client.NotifyBlocks(); err != nil {
117108
log.Printf("%s: Cannot register for block notifications: %v", miner, err)
118109
return miner, err
119110
}
120111

121-
log.Printf("%s: Generating %v blocks...", miner, *startBlock)
122112
return miner, nil
123113
}
124114

125-
// StartMining sets the cpu miner to mine coins
126-
func (m *Miner) StartMining() error {
127-
if err := m.client.SetGenerate(true, 1); err != nil {
128-
log.Printf("%s: Cannot start mining: %v", m, err)
129-
return err
130-
}
131-
return nil
132-
}
133-
134-
// StopMining stops the cpu miner from mining coins
135-
func (m *Miner) StopMining() error {
136-
if err := m.client.SetGenerate(false, 0); err != nil {
137-
log.Printf("%s: Cannot stop mining: %v", m, err)
115+
// Generate makes the CPU miner mine the requested number of blocks
116+
func (m *Miner) Generate(numBlocks uint32) error {
117+
if _, err := m.client.Generate(numBlocks); err != nil {
118+
log.Printf("%s: Cannot generate %d blocks: %v", m, numBlocks, err)
138119
return err
139120
}
140121
return nil

‎simulation.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (s *Simulation) Start() error {
189189
}
190190

191191
for i := 0; i < *numActors; i++ {
192-
a, err := NewActor(node, uint16(18557+i))
192+
a, err := NewActor(uint16(18557 + i))
193193
if err != nil {
194194
log.Printf("%s: Cannot create actor: %v", a, err)
195195
continue

0 commit comments

Comments
 (0)
Please sign in to comment.