[Ethereum] How does Ethereum regulate the time between blocks

block-intervaltimestamp

I was reading "Explanation of genesis file" and I found the description of the timestamp:

A scalar value equal to the reasonable output of Unix’ time() function
at this block inception.

This mechanism enforces a homeostasis in terms of the time between
blocks. A smaller period between the last two blocks results in an
increase in the difficulty level and thus additional computation
required to find the next valid block. If the period is too large, the
difficulty, and expected time to the next block, is reduced.

The timestamp also allows to verify the order of block within the
chain (Yellowpaper, 4.3.4. (43)).

Note: Homeostasis is the property of a system in which variables are
regulated so that internal conditions remain stable and relatively
constant.

How does, generally speaking, Ethereum maintain it's homeostasis and regulate the time between blocks? Now it's 15 sec, but is it possible for the Ethereum developers to increase or decrease that time without touching the client or is this a paramether harcoded in the client? How can I set, for example, a 30 sec time between blocks on my testnet?

Best Answer

If you are using geth here's a patch that I use to accelerate mining. You could probably modify it to decelerate mining if you wish. (I'm curious why you wish to go slower). In any event, I think the answer to "how does the interval for mining get set" is "not very clear from the code"... but this patch should give you a head start in understanding the timing of geth.

diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go
index d88d919..f03fd30 100644
--- a/eth/fetcher/fetcher.go
+++ b/eth/fetcher/fetcher.go
@@ -34,7 +34,7 @@ import (
 const (
    arriveTimeout = 500 * time.Millisecond // Time allowance before an announced block is explicitlrd
    gatherSlack   = 100 * time.Millisecond // Interval used to collate almost-expired announces witfs
-   fetchTimeout  = 5 * time.Second        // Maximum alloted time to return an explicitly requestebk
+   fetchTimeout  = 1 * time.Second        // Maximum alloted time to return an explicitly requestebk
    maxUncleDist  = 7                      // Maximum allowed backward distance from the chain head
    maxQueueDist  = 32                     // Maximum allowed distance from the chain head to queue
    hashLimit     = 256                    // Maximum number of unique blocks a peer may have annoued
diff --git a/eth/peer.go b/eth/peer.go
index 15ba22f..0201057 100644
--- a/eth/peer.go
+++ b/eth/peer.go
@@ -41,7 +41,7 @@ var (
 const (
    maxKnownTxs      = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS)
    maxKnownBlocks   = 1024  // Maximum block hashes to keep in the known list (prevent DOS)
-   handshakeTimeout = 5 * time.Second
+   handshakeTimeout = 1 * time.Second
 )

 // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known
diff --git a/miner/worker.go b/miner/worker.go
index 754a6fc..2b62b59 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -466,7 +466,7 @@ func (self *worker) commitNewWork() {
            tstamp = parent.Time().Int64() + 1
    }
    // this will ensure we're not going off too far in the future
-   if now := time.Now().Unix(); tstamp > now+4 {
+   if now := time.Now().Unix(); tstamp > now {
            wait := time.Duration(tstamp-now) * time.Second
            glog.V(logger.Info).Infoln("We are too far in the future. Waiting for", wait)
            time.Sleep(wait)
diff --git a/p2p/rlpx.go b/p2p/rlpx.go
index aaa7338..ce82eb7 100644
--- a/p2p/rlpx.go
+++ b/p2p/rlpx.go
@@ -57,7 +57,7 @@ const (

    // total timeout for encryption handshake and protocol
    // handshake in both directions.
-   handshakeTimeout = 5 * time.Second
+   handshakeTimeout = 2 * time.Second

    // This is the timeout for sending the disconnect reason.
    // This is shorter than the usual timeout because we don't want
diff --git a/params/protocol_params.go b/params/protocol_params.go
index dcc17e0..21a49c5 100755
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -29,10 +29,10 @@ var (
    CallNewAccountGas      = big.NewInt(25000)  // Paid for CALL when the destination address didn'e.
    TxGas                  = big.NewInt(21000)  // Per transaction. NOTE: Not payable on data of cas.
    TxDataZeroGas          = big.NewInt(4)      // Per byte of data attached to a transaction that u.
-   DifficultyBoundDivisor = big.NewInt(2048)   // The bound divisor of the difficulty, used in thep.
+   DifficultyBoundDivisor = big.NewInt(1)      // The bound divisor of the difficulty, used in thep.
    QuadCoeffDiv           = big.NewInt(512)    // Divisor for the quadratic particle of the memoryo.
-   GenesisDifficulty      = big.NewInt(131072) // Difficulty of the Genesis block.
-   DurationLimit          = big.NewInt(13)     // The decision boundary on the blocktime duration e.
+   GenesisDifficulty      = big.NewInt(1)      // Difficulty of the Genesis block.
+   DurationLimit          = big.NewInt(1)      // The decision boundary on the blocktime duration e.
    SstoreSetGas           = big.NewInt(20000)  // Once per SLOAD operation.
    LogDataGas             = big.NewInt(8)      // Per byte in a LOG* operation's data.
    CallStipend            = big.NewInt(2300)   // Free gas given at beginning of call.
@@ -57,7 +57,7 @@ var (
    CreateDataGas        = big.NewInt(200)    //
    Ripemd160Gas         = big.NewInt(600)    //
    Ripemd160WordGas     = big.NewInt(120)    //
-   MinimumDifficulty    = big.NewInt(131072) // The minimum that the difficulty may ever be.
+   MinimumDifficulty    = big.NewInt(1)      // The minimum that the difficulty may ever be.
    CallCreateDepth      = big.NewInt(1024)   // Maximum depth of call/create stack.
    ExpGas               = big.NewInt(10)     // Once per EXP instuction.
    LogGas               = big.NewInt(375)    // Per LOG* operation.