chaincfg: use DeploymentStarter/DeploymentEnder instead of start/end times

In this commit, we utilize the recently added ConsensusDeploymentStarter
and ConsensusDeploymentEnder interfaces. Concrete implementations of
this interface based on the median time past comparison are used now in
the ConsensusDeployment struct instead of hard coded start/end times.

Along the way, we had to switch to using the "zero time": time.Time{},
in place of 0 and math.MaxInt64 as comparison (After/Before) seems to be
broken in the Go stdlib for times very far in the future. It appears Go
isn't ready to handle the heat death of the universe.
This commit is contained in:
Olaoluwa Osuntokun 2021-03-19 17:16:26 -07:00
parent dc4dc15d8c
commit 2b6370dfd7
No known key found for this signature in database
GPG key ID: 3BBD59E99B280306
3 changed files with 134 additions and 60 deletions

View file

@ -80,7 +80,9 @@ type MedianTimeDeploymentStarter struct {
} }
// NewMedianTimeDeploymentStarter returns a new instance of a // NewMedianTimeDeploymentStarter returns a new instance of a
// MedianTimeDeploymentStarter for a given start time. // MedianTimeDeploymentStarter for a given start time. Using a time.Time
// instance where IsZero() is true, indicates that a deployment should be
// considered to always have been started.
func NewMedianTimeDeploymentStarter(startTime time.Time) *MedianTimeDeploymentStarter { func NewMedianTimeDeploymentStarter(startTime time.Time) *MedianTimeDeploymentStarter {
return &MedianTimeDeploymentStarter{ return &MedianTimeDeploymentStarter{
startTime: startTime, startTime: startTime,
@ -134,7 +136,9 @@ type MedianTimeDeploymentEnder struct {
} }
// NewMedianTimeDeploymentEnder returns a new instance of the // NewMedianTimeDeploymentEnder returns a new instance of the
// MedianTimeDeploymentEnder anchored around the passed endTime. // MedianTimeDeploymentEnder anchored around the passed endTime. Using a
// time.Time instance where IsZero() is true, indicates that a deployment
// should be considered to never end.
func NewMedianTimeDeploymentEnder(endTime time.Time) *MedianTimeDeploymentEnder { func NewMedianTimeDeploymentEnder(endTime time.Time) *MedianTimeDeploymentEnder {
return &MedianTimeDeploymentEnder{ return &MedianTimeDeploymentEnder{
endTime: endTime, endTime: endTime,

View file

@ -8,7 +8,6 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"errors" "errors"
"math"
"math/big" "math/big"
"strings" "strings"
"time" "time"
@ -95,13 +94,13 @@ type ConsensusDeployment struct {
// this particular soft-fork deployment refers to. // this particular soft-fork deployment refers to.
BitNumber uint8 BitNumber uint8
// StartTime is the median block time after which voting on the // DeploymentStarter is used to determine if the given
// deployment starts. // ConsensusDeployment has started or not.
StartTime uint64 DeploymentStarter ConsensusDeploymentStarter
// ExpireTime is the median block time after which the attempted // DeploymentEnder is used to determine if the given
// deployment expires. // ConsensusDeployment has ended or not.
ExpireTime uint64 DeploymentEnder ConsensusDeploymentEnder
} }
// Constants that define the deployment offset in the deployments field of the // Constants that define the deployment offset in the deployments field of the
@ -320,19 +319,31 @@ var MainNetParams = Params{
MinerConfirmationWindow: 2016, // MinerConfirmationWindow: 2016, //
Deployments: [DefinedDeployments]ConsensusDeployment{ Deployments: [DefinedDeployments]ConsensusDeployment{
DeploymentTestDummy: { DeploymentTestDummy: {
BitNumber: 28, BitNumber: 28,
StartTime: 1199145601, // January 1, 2008 UTC DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1230767999, // December 31, 2008 UTC time.Unix(11991456010, 0), // January 1, 2008 UTC
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1230767999, 0), // December 31, 2008 UTC
),
}, },
DeploymentCSV: { DeploymentCSV: {
BitNumber: 0, BitNumber: 0,
StartTime: 1462060800, // May 1st, 2016 DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1493596800, // May 1st, 2017 time.Unix(1462060800, 0), // May 1st, 2016
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1493596800, 0), // May 1st, 2017
),
}, },
DeploymentSegwit: { DeploymentSegwit: {
BitNumber: 1, BitNumber: 1,
StartTime: 1479168000, // November 15, 2016 UTC DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1510704000, // November 15, 2017 UTC. time.Unix(1479168000, 0), // November 15, 2016 UTC
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1510704000, 0), // November 15, 2017 UTC.
),
}, },
}, },
@ -396,19 +407,31 @@ var RegressionNetParams = Params{
MinerConfirmationWindow: 144, MinerConfirmationWindow: 144,
Deployments: [DefinedDeployments]ConsensusDeployment{ Deployments: [DefinedDeployments]ConsensusDeployment{
DeploymentTestDummy: { DeploymentTestDummy: {
BitNumber: 28, BitNumber: 28,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
DeploymentCSV: { DeploymentCSV: {
BitNumber: 0, BitNumber: 0,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
DeploymentSegwit: { DeploymentSegwit: {
BitNumber: 1, BitNumber: 1,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires. time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires.
),
}, },
}, },
@ -490,19 +513,31 @@ var TestNet3Params = Params{
MinerConfirmationWindow: 2016, MinerConfirmationWindow: 2016,
Deployments: [DefinedDeployments]ConsensusDeployment{ Deployments: [DefinedDeployments]ConsensusDeployment{
DeploymentTestDummy: { DeploymentTestDummy: {
BitNumber: 28, BitNumber: 28,
StartTime: 1199145601, // January 1, 2008 UTC DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1230767999, // December 31, 2008 UTC time.Unix(1199145601, 0), // January 1, 2008 UTC
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1230767999, 0), // December 31, 2008 UTC
),
}, },
DeploymentCSV: { DeploymentCSV: {
BitNumber: 0, BitNumber: 0,
StartTime: 1456790400, // March 1st, 2016 DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1493596800, // May 1st, 2017 time.Unix(1456790400, 0), // March 1st, 2016
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1493596800, 0), // May 1st, 2017
),
}, },
DeploymentSegwit: { DeploymentSegwit: {
BitNumber: 1, BitNumber: 1,
StartTime: 1462060800, // May 1, 2016 UTC DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1493596800, // May 1, 2017 UTC. time.Unix(1462060800, 0), // May 1, 2016 UTC
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1493596800, 0), // May 1, 2017 UTC.
),
}, },
}, },
@ -570,19 +605,31 @@ var SimNetParams = Params{
MinerConfirmationWindow: 100, MinerConfirmationWindow: 100,
Deployments: [DefinedDeployments]ConsensusDeployment{ Deployments: [DefinedDeployments]ConsensusDeployment{
DeploymentTestDummy: { DeploymentTestDummy: {
BitNumber: 28, BitNumber: 28,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
DeploymentCSV: { DeploymentCSV: {
BitNumber: 0, BitNumber: 0,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
DeploymentSegwit: { DeploymentSegwit: {
BitNumber: 1, BitNumber: 1,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires. time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires.
),
}, },
}, },
@ -665,24 +712,40 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params {
MinerConfirmationWindow: 2016, MinerConfirmationWindow: 2016,
Deployments: [DefinedDeployments]ConsensusDeployment{ Deployments: [DefinedDeployments]ConsensusDeployment{
DeploymentTestDummy: { DeploymentTestDummy: {
BitNumber: 28, BitNumber: 28,
StartTime: 1199145601, // January 1, 2008 UTC DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: 1230767999, // December 31, 2008 UTC time.Unix(1199145601, 0), // January 1, 2008 UTC
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Unix(1230767999, 0), // December 31, 2008 UTC
),
}, },
DeploymentCSV: { DeploymentCSV: {
BitNumber: 29, BitNumber: 29,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
DeploymentSegwit: { DeploymentSegwit: {
BitNumber: 29, BitNumber: 29,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires. time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
DeploymentTaproot: { DeploymentTaproot: {
BitNumber: 29, BitNumber: 29,
StartTime: 0, // Always available for vote DeploymentStarter: NewMedianTimeDeploymentStarter(
ExpireTime: math.MaxInt64, // Never expires. time.Time{}, // Always available for vote
),
DeploymentEnder: NewMedianTimeDeploymentEnder(
time.Time{}, // Never expires
),
}, },
}, },

View file

@ -31,6 +31,7 @@ import (
"github.com/btcsuite/btcd/blockchain/indexers" "github.com/btcsuite/btcd/blockchain/indexers"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database"
@ -40,7 +41,6 @@ import (
"github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/peer"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/websocket" "github.com/btcsuite/websocket"
) )
@ -1289,11 +1289,18 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str
// Finally, populate the soft-fork description with all the // Finally, populate the soft-fork description with all the
// information gathered above. // information gathered above.
var startTime, endTime int64
if starter, ok := deploymentDetails.DeploymentStarter.(*chaincfg.MedianTimeDeploymentStarter); ok {
startTime = starter.StartTime().Unix()
}
if ender, ok := deploymentDetails.DeploymentEnder.(*chaincfg.MedianTimeDeploymentEnder); ok {
endTime = ender.EndTime().Unix()
}
chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{
Status: strings.ToLower(statusString), Status: strings.ToLower(statusString),
Bit: deploymentDetails.BitNumber, Bit: deploymentDetails.BitNumber,
StartTime2: int64(deploymentDetails.StartTime), StartTime2: startTime,
Timeout: int64(deploymentDetails.ExpireTime), Timeout: endTime,
} }
} }