From 37f247ff4301958a42c15c6aeff68233907388de Mon Sep 17 00:00:00 2001
From: Dan Laine <daniel.laine@avalabs.org>
Date: Thu, 17 Dec 2020 15:14:12 -0500
Subject: renamings; add comments

---
 plugin/evm/vm.go | 144 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 87 insertions(+), 57 deletions(-)

(limited to 'plugin/evm')

diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
index c9bdad9..f125564 100644
--- a/plugin/evm/vm.go
+++ b/plugin/evm/vm.go
@@ -69,19 +69,15 @@ const (
 	maxBlockTime    = 1000 * time.Millisecond
 	batchSize       = 250
 	maxUTXOsToFetch = 1024
-	blockCacheSize  = 1 << 10 // 1024
+	blockCacheSize  = 1024
 	codecVersion    = uint16(0)
 )
 
 const (
-	bdTimerStateMin = iota
-	bdTimerStateMax
-	bdTimerStateLong
+	txFee = units.MilliAvax
 )
 
 var (
-	txFee = units.MilliAvax
-
 	errEmptyBlock                 = errors.New("empty block")
 	errCreateBlock                = errors.New("couldn't create block")
 	errUnknownBlock               = errors.New("unknown block")
@@ -103,6 +99,17 @@ var (
 	errInvalidNonce               = errors.New("invalid nonce")
 )
 
+// mayBuildBlockStatus denotes whether the engine should be notified
+// that a block should be built, or whether more time has to pass
+// before doing so. See VM's [mayBuildBlock].
+type mayBuildBlockStatus uint8
+
+const (
+	wait mayBuildBlockStatus = iota
+	conditionalWait
+	build
+)
+
 func maxDuration(x, y time.Duration) time.Duration {
 	if x > y {
 		return x
@@ -145,14 +152,16 @@ type VM struct {
 
 	CLIConfig CommandLineConfig
 
-	chainID          *big.Int
-	networkID        uint64
-	genesisHash      common.Hash
-	chain            *coreth.ETHChain
-	chaindb          Database
-	newBlockChan     chan *Block
-	networkChan      chan<- commonEng.Message
-	newMinedBlockSub *event.TypeMuxSubscription
+	chainID      *big.Int
+	networkID    uint64
+	genesisHash  common.Hash
+	chain        *coreth.ETHChain
+	chaindb      Database
+	newBlockChan chan *Block
+	// A message is sent on this channel when a new block
+	// is ready to be build. This notifies the consensus engine.
+	notifyBuildBlockChan chan<- commonEng.Message
+	newMinedBlockSub     *event.TypeMuxSubscription
 
 	acceptedDB database.Database
 
@@ -165,11 +174,27 @@ type VM struct {
 	lastAccepted                 *Block
 	writingMetadata              uint32
 
-	bdlock          sync.Mutex
-	blockDelayTimer *timer.Timer
-	bdTimerState    int8
-	bdGenWaitFlag   bool
-	bdGenFlag       bool
+	// [buildBlockLock] must be held when accessing [mayBuildBlock],
+	// [tryToBuildBlock] or [awaitingBuildBlock].
+	buildBlockLock sync.Mutex
+	// [buildBlockTimer] periodically fires in order to update [mayBuildBlock]
+	// and to try to build a block, if applicable.
+	buildBlockTimer *timer.Timer
+	// [mayBuildBlock] == [wait] means that the next block may be built
+	// only after more time has elapsed.
+	// [mayBuildBlock] == [conditionalWait] means that the next block may be built
+	// only if it has more than [batchSize] txs in it. Otherwise, wait until more
+	// time has elapsed.
+	// [mayBuildBlock] == [build] means that the next block may be built
+	// at any time.
+	mayBuildBlock mayBuildBlockStatus
+	// If true, try to notify the engine that a block should be built.
+	// Engine may not be notified because [mayBuildBlock] says to wait.
+	tryToBuildBlock bool
+	// If true, the engine has been notified that it should build a block
+	// but has not done so yet. If this is the case, wait until it has
+	// built a block before notifying it again.
+	awaitingBuildBlock bool
 
 	genlock               sync.Mutex
 	txSubmitChan          <-chan struct{}
@@ -329,26 +354,31 @@ func (vm *VM) Initialize(
 	vm.blockStatusCache = cache.LRU{Size: blockCacheSize}
 	vm.blockAtomicInputCache = cache.LRU{Size: blockCacheSize}
 	vm.newBlockChan = make(chan *Block)
-	vm.networkChan = toEngine
-	vm.blockDelayTimer = timer.NewTimer(func() {
-		vm.bdlock.Lock()
-		switch vm.bdTimerState {
-		case bdTimerStateMin:
-			vm.bdTimerState = bdTimerStateMax
-			vm.blockDelayTimer.SetTimeoutIn(maxDuration(maxBlockTime-minBlockTime, 0))
-		case bdTimerStateMax:
-			vm.bdTimerState = bdTimerStateLong
+	vm.notifyBuildBlockChan = toEngine
+
+	// Periodically updates [vm.mayBuildBlock] and tries to notify the engine to build
+	// a new block, if applicable.
+	vm.buildBlockTimer = timer.NewTimer(func() {
+		vm.buildBlockLock.Lock()
+		switch vm.mayBuildBlock {
+		case wait:
+			// Some time has passed. Allow block to be built if it has enough txs in it.
+			vm.mayBuildBlock = conditionalWait
+			vm.buildBlockTimer.SetTimeoutIn(maxDuration(maxBlockTime-minBlockTime, 0))
+		case conditionalWait:
+			// More time has passed. Allow block to be built regardless of tx count.
+			vm.mayBuildBlock = build
 		}
-		tryAgain := vm.bdGenWaitFlag
-		vm.bdlock.Unlock()
-		if tryAgain {
+		tryBuildBlock := vm.tryToBuildBlock
+		vm.buildBlockLock.Unlock()
+		if tryBuildBlock {
 			vm.tryBlockGen()
 		}
 	})
-	go ctx.Log.RecoverAndPanic(vm.blockDelayTimer.Dispatch)
+	go ctx.Log.RecoverAndPanic(vm.buildBlockTimer.Dispatch)
 
-	vm.bdTimerState = bdTimerStateLong
-	vm.bdGenWaitFlag = true
+	vm.mayBuildBlock = build
+	vm.tryToBuildBlock = true
 	vm.txPoolStabilizedOk = make(chan struct{}, 1)
 	// TODO: read size from options
 	vm.pendingAtomicTxs = make(chan *Tx, 1024)
@@ -411,7 +441,7 @@ func (vm *VM) Shutdown() error {
 	}
 
 	vm.writeBackMetadata()
-	vm.blockDelayTimer.Stop()
+	vm.buildBlockTimer.Stop()
 	close(vm.shutdownChan)
 	vm.chain.Stop()
 	vm.shutdownWg.Wait()
@@ -423,15 +453,13 @@ func (vm *VM) BuildBlock() (snowman.Block, error) {
 	vm.chain.GenBlock()
 	block := <-vm.newBlockChan
 
-	// reset the min block time timer
-	// after finishing attempt to build
-	// a block.
-	vm.bdlock.Lock()
-	vm.bdTimerState = bdTimerStateMin
-	vm.bdGenWaitFlag = false
-	vm.bdGenFlag = false
-	vm.blockDelayTimer.SetTimeoutIn(minBlockTime)
-	vm.bdlock.Unlock()
+	vm.buildBlockLock.Lock()
+	// Specify that we should wait before trying to build another block.
+	vm.mayBuildBlock = wait
+	vm.tryToBuildBlock = false
+	vm.awaitingBuildBlock = false
+	vm.buildBlockTimer.SetTimeoutIn(minBlockTime)
+	vm.buildBlockLock.Unlock()
 
 	if block == nil {
 		return nil, errCreateBlock
@@ -578,13 +606,14 @@ func (vm *VM) updateStatus(blockID ids.ID, status choices.Status) {
 }
 
 func (vm *VM) tryBlockGen() error {
-	vm.bdlock.Lock()
-	defer vm.bdlock.Unlock()
-	if vm.bdGenFlag {
-		// skip if one call already generates a block in this round
+	vm.buildBlockLock.Lock()
+	defer vm.buildBlockLock.Unlock()
+	if vm.awaitingBuildBlock {
+		// We notified the engine that a block should be built but it hasn't
+		// done so yet. Wait until it has done so before notifying again.
 		return nil
 	}
-	vm.bdGenWaitFlag = true
+	vm.tryToBuildBlock = true
 
 	vm.genlock.Lock()
 	defer vm.genlock.Unlock()
@@ -597,20 +626,21 @@ func (vm *VM) tryBlockGen() error {
 		return nil
 	}
 
-	switch vm.bdTimerState {
-	case bdTimerStateMin:
+	switch vm.mayBuildBlock {
+	case wait: // Wait more time before notifying engine to building a block
 		return nil
-	case bdTimerStateMax:
+	case conditionalWait: // Notify engine only if there are enough pending txs
 		if size < batchSize {
 			return nil
 		}
-	case bdTimerStateLong:
-		// timeout; go ahead and generate a new block anyway
+	case build: // Notify engine
+	default:
+		panic(fmt.Sprintf("mayBuildBlock has unexpected value %d", vm.mayBuildBlock))
 	}
 	select {
-	case vm.networkChan <- commonEng.PendingTxs:
-		// successfully push out the notification; this round ends
-		vm.bdGenFlag = true
+	case vm.notifyBuildBlockChan <- commonEng.PendingTxs:
+		// Notify engine to build a block
+		vm.awaitingBuildBlock = true
 	default:
 		return errBlockFrequency
 	}
-- 
cgit v1.2.3-70-g09d2


From f20fd5437ec5144a926589395cece29f2052994d Mon Sep 17 00:00:00 2001
From: Dan Laine <daniel.laine@avalabs.org>
Date: Thu, 17 Dec 2020 16:53:56 -0500
Subject: rename mayBuildBlockStatus values

---
 plugin/evm/vm.go | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

(limited to 'plugin/evm')

diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
index 231db2a..9335b51 100644
--- a/plugin/evm/vm.go
+++ b/plugin/evm/vm.go
@@ -105,9 +105,9 @@ var (
 type mayBuildBlockStatus uint8
 
 const (
-	wait mayBuildBlockStatus = iota
-	conditionalWait
-	build
+	waitToBuild mayBuildBlockStatus = iota
+	conditionalWaitToBuild
+	mayBuild
 )
 
 func maxDuration(x, y time.Duration) time.Duration {
@@ -361,13 +361,13 @@ func (vm *VM) Initialize(
 	vm.buildBlockTimer = timer.NewTimer(func() {
 		vm.buildBlockLock.Lock()
 		switch vm.mayBuildBlock {
-		case wait:
+		case waitToBuild:
 			// Some time has passed. Allow block to be built if it has enough txs in it.
-			vm.mayBuildBlock = conditionalWait
+			vm.mayBuildBlock = conditionalWaitToBuild
 			vm.buildBlockTimer.SetTimeoutIn(maxDuration(maxBlockTime-minBlockTime, 0))
-		case conditionalWait:
+		case conditionalWaitToBuild:
 			// More time has passed. Allow block to be built regardless of tx count.
-			vm.mayBuildBlock = build
+			vm.mayBuildBlock = mayBuild
 		}
 		tryBuildBlock := vm.tryToBuildBlock
 		vm.buildBlockLock.Unlock()
@@ -377,7 +377,7 @@ func (vm *VM) Initialize(
 	})
 	go ctx.Log.RecoverAndPanic(vm.buildBlockTimer.Dispatch)
 
-	vm.mayBuildBlock = build
+	vm.mayBuildBlock = mayBuild
 	vm.tryToBuildBlock = true
 	vm.txPoolStabilizedOk = make(chan struct{}, 1)
 	// TODO: read size from options
@@ -455,7 +455,7 @@ func (vm *VM) BuildBlock() (snowman.Block, error) {
 
 	vm.buildBlockLock.Lock()
 	// Specify that we should wait before trying to build another block.
-	vm.mayBuildBlock = wait
+	vm.mayBuildBlock = waitToBuild
 	vm.tryToBuildBlock = false
 	vm.awaitingBuildBlock = false
 	vm.buildBlockTimer.SetTimeoutIn(minBlockTime)
@@ -627,13 +627,13 @@ func (vm *VM) tryBlockGen() error {
 	}
 
 	switch vm.mayBuildBlock {
-	case wait: // Wait more time before notifying engine to building a block
+	case waitToBuild: // Wait more time before notifying engine to building a block
 		return nil
-	case conditionalWait: // Notify engine only if there are enough pending txs
+	case conditionalWaitToBuild: // Notify engine only if there are enough pending txs
 		if size < batchSize {
 			return nil
 		}
-	case build: // Notify engine
+	case mayBuild: // Notify engine
 	default:
 		panic(fmt.Sprintf("mayBuildBlock has unexpected value %d", vm.mayBuildBlock))
 	}
-- 
cgit v1.2.3-70-g09d2