Correct RPC time handling for getblocktemplate.

This commit modifies the getblocktemplate RPC to correctly handle the
curtime field.

Currently, the RPC server will refuse to serve a block template if the
current time is before the minimum allowed time for a block even though
the real generated block template already accounted for it.

This consists of three changes:
- Remove the unnecessary and incorrect check in the RPC invocation for the
  current time against the min required time since it is already handled
  properly by the block template generation.
- Expose the network time source to the RPC work state and use the
  adjusted time for checking against the maximum allowed time instead of
  the current time.
- Set the returned RPC result curtime field to the time of the generated
  block header.

Fixes #209.
This commit is contained in:
Dave Collins 2015-01-08 00:57:13 -06:00
parent 4b727d2035
commit a64ffb820a

View file

@ -247,13 +247,15 @@ type gbtWorkState struct {
minTimestamp time.Time
template *BlockTemplate
notifyMap map[btcwire.ShaHash]map[int64]chan struct{}
timeSource btcchain.MedianTimeSource
}
// newGbtWorkState returns a new instance of a gbtWorkState with all internal
// fields initialized and ready to use.
func newGbtWorkState() *gbtWorkState {
func newGbtWorkState(timeSource btcchain.MedianTimeSource) *gbtWorkState {
return &gbtWorkState{
notifyMap: make(map[btcwire.ShaHash]map[int64]chan struct{}),
notifyMap: make(map[btcwire.ShaHash]map[int64]chan struct{}),
timeSource: timeSource,
}
}
@ -519,7 +521,7 @@ func newRPCServer(listenAddrs []string, s *server) (*rpcServer, error) {
server: s,
statusLines: make(map[int]string),
workState: newWorkState(),
gbtWorkState: newGbtWorkState(),
gbtWorkState: newGbtWorkState(s.timeSource),
quit: make(chan int),
}
rpc.ntfnMgr = newWsNotificationManager(&rpc)
@ -1546,23 +1548,15 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
template := state.template
msgBlock := template.block
header := &msgBlock.Header
curTime := time.Now()
if curTime.Before(state.minTimestamp) {
return nil, btcjson.Error{
Code: btcjson.ErrOutOfRange.Code,
Message: fmt.Sprintf("The local time is before the "+
"minimum allowed time for a block - current "+
"time %v, minimum time %v", curTime,
state.minTimestamp),
}
}
maxTime := curTime.Add(time.Second * btcchain.MaxTimeOffsetSeconds)
adjustedTime := state.timeSource.AdjustedTime()
maxTime := adjustedTime.Add(time.Second * btcchain.MaxTimeOffsetSeconds)
if header.Timestamp.After(maxTime) {
return nil, btcjson.Error{
Code: btcjson.ErrOutOfRange.Code,
Message: fmt.Sprintf("The template time is after the "+
"maximum allowed time for a block - template "+
"time %v, maximum time %v", curTime, maxTime),
"time %v, maximum time %v", adjustedTime,
maxTime),
}
}
@ -1625,7 +1619,7 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
templateID := encodeTemplateID(state.prevHash, state.lastGenerated)
reply := btcjson.GetBlockTemplateResult{
Bits: strconv.FormatInt(int64(header.Bits), 16),
CurTime: curTime.Unix(),
CurTime: header.Timestamp.Unix(),
Height: template.height,
PreviousHash: header.PrevBlock.String(),
SigOpLimit: btcchain.MaxSigOpsPerBlock,