Skip to content

Commit

Permalink
Correct RPC time handling for getblocktemplate.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
davecgh committed Jan 8, 2015
1 parent 4b727d2 commit eef7ce4
Showing 1 changed file with 10 additions and 16 deletions.
26 changes: 10 additions & 16 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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),
}
}

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit eef7ce4

Please sign in to comment.