github.com/decred/dcrd/blockchain@v1.2.1/blockindex.go (about) 1 // Copyright (c) 2013-2017 The btcsuite developers 2 // Copyright (c) 2018 The Decred developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package blockchain 7 8 import ( 9 "bytes" 10 "math/big" 11 "sort" 12 "sync" 13 "time" 14 15 "github.com/decred/dcrd/blockchain/stake" 16 "github.com/decred/dcrd/blockchain/standalone" 17 "github.com/decred/dcrd/chaincfg/chainhash" 18 "github.com/decred/dcrd/database" 19 "github.com/decred/dcrd/wire" 20 ) 21 22 // blockStatus is a bit field representing the validation state of the block. 23 type blockStatus byte 24 25 // The following constants specify possible status bit flags for a block. 26 // 27 // NOTE: This section specifically does not use iota since the block status is 28 // serialized and must be stable for long-term storage. 29 const ( 30 // statusNone indicates that the block has no validation state flags set. 31 statusNone blockStatus = 0 32 33 // statusDataStored indicates that the block's payload is stored on disk. 34 statusDataStored blockStatus = 1 << 0 35 36 // statusValid indicates that the block has been fully validated. It also 37 // means that all of its ancestors have also been validated. 38 statusValid blockStatus = 1 << 1 39 40 // statusValidateFailed indicates that the block has failed validation. 41 statusValidateFailed blockStatus = 1 << 2 42 43 // statusInvalidAncestor indicates that one of the ancestors of the block 44 // has failed validation, thus the block is also invalid. 45 statusInvalidAncestor blockStatus = 1 << 3 46 ) 47 48 // HaveData returns whether the full block data is stored in the database. This 49 // will return false for a block node where only the header is downloaded or 50 // stored. 51 func (status blockStatus) HaveData() bool { 52 return status&statusDataStored != 0 53 } 54 55 // KnownValid returns whether the block is known to be valid. This will return 56 // false for a valid block that has not been fully validated yet. 57 func (status blockStatus) KnownValid() bool { 58 return status&statusValid != 0 59 } 60 61 // KnownInvalid returns whether the block is known to be invalid. This will 62 // return false for invalid blocks that have not been proven invalid yet. 63 func (status blockStatus) KnownInvalid() bool { 64 return status&(statusValidateFailed|statusInvalidAncestor) != 0 65 } 66 67 // blockNode represents a block within the block chain and is primarily used to 68 // aid in selecting the best chain to be the main chain. The main chain is 69 // stored into the block database. 70 type blockNode struct { 71 // NOTE: Additions, deletions, or modifications to the order of the 72 // definitions in this struct should not be changed without considering 73 // how it affects alignment on 64-bit platforms. The current order is 74 // specifically crafted to result in minimal padding. There will be 75 // hundreds of thousands of these in memory, so a few extra bytes of 76 // padding adds up. 77 78 // parent is the parent block for this node. 79 parent *blockNode 80 81 // hash is the hash of the block this node represents. 82 hash chainhash.Hash 83 84 // workSum is the total amount of work in the chain up to and including 85 // this node. 86 workSum *big.Int 87 88 // Some fields from block headers to aid in best chain selection and 89 // reconstructing headers from memory. These must be treated as 90 // immutable and are intentionally ordered to avoid padding on 64-bit 91 // platforms. 92 height int64 93 voteBits uint16 94 finalState [6]byte 95 blockVersion int32 96 voters uint16 97 freshStake uint8 98 revocations uint8 99 poolSize uint32 100 bits uint32 101 sbits int64 102 timestamp int64 103 merkleRoot chainhash.Hash 104 stakeRoot chainhash.Hash 105 blockSize uint32 106 nonce uint32 107 extraData [32]byte 108 stakeVersion uint32 109 110 // status is a bitfield representing the validation state of the block. 111 // This field, unlike the other fields, may be changed after the block 112 // node is created, so it must only be accessed or updated using the 113 // concurrent-safe NodeStatus, SetStatusFlags, and UnsetStatusFlags 114 // methods on blockIndex once the node has been added to the index. 115 status blockStatus 116 117 // stakeNode contains all the consensus information required for the 118 // staking system. The node also caches information required to add or 119 // remove stake nodes, so that the stake node itself may be pruneable 120 // to save memory while maintaining high throughput efficiency for the 121 // evaluation of sidechains. 122 stakeNode *stake.Node 123 newTickets []chainhash.Hash 124 ticketsVoted []chainhash.Hash 125 ticketsRevoked []chainhash.Hash 126 127 // Keep track of all vote version and bits in this block. 128 votes []stake.VoteVersionTuple 129 } 130 131 // initBlockNode initializes a block node from the given header, initialization 132 // vector for the ticket lottery, and parent node. The workSum is calculated 133 // based on the parent, or, in the case no parent is provided, it will just be 134 // the work for the passed block. 135 // 136 // This function is NOT safe for concurrent access. It must only be called when 137 // initially creating a node. 138 func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *blockNode) { 139 *node = blockNode{ 140 hash: blockHeader.BlockHash(), 141 workSum: standalone.CalcWork(blockHeader.Bits), 142 height: int64(blockHeader.Height), 143 blockVersion: blockHeader.Version, 144 voteBits: blockHeader.VoteBits, 145 finalState: blockHeader.FinalState, 146 voters: blockHeader.Voters, 147 freshStake: blockHeader.FreshStake, 148 poolSize: blockHeader.PoolSize, 149 bits: blockHeader.Bits, 150 sbits: blockHeader.SBits, 151 timestamp: blockHeader.Timestamp.Unix(), 152 merkleRoot: blockHeader.MerkleRoot, 153 stakeRoot: blockHeader.StakeRoot, 154 revocations: blockHeader.Revocations, 155 blockSize: blockHeader.Size, 156 nonce: blockHeader.Nonce, 157 extraData: blockHeader.ExtraData, 158 stakeVersion: blockHeader.StakeVersion, 159 } 160 if parent != nil { 161 node.parent = parent 162 node.workSum = node.workSum.Add(parent.workSum, node.workSum) 163 } 164 } 165 166 // newBlockNode returns a new block node for the given block header and parent 167 // node. The workSum is calculated based on the parent, or, in the case no 168 // parent is provided, it will just be the work for the passed block. 169 func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode { 170 var node blockNode 171 initBlockNode(&node, blockHeader, parent) 172 return &node 173 } 174 175 // Header constructs a block header from the node and returns it. 176 // 177 // This function is safe for concurrent access. 178 func (node *blockNode) Header() wire.BlockHeader { 179 // No lock is needed because all accessed fields are immutable. 180 prevHash := zeroHash 181 if node.parent != nil { 182 prevHash = &node.parent.hash 183 } 184 return wire.BlockHeader{ 185 Version: node.blockVersion, 186 PrevBlock: *prevHash, 187 MerkleRoot: node.merkleRoot, 188 StakeRoot: node.stakeRoot, 189 VoteBits: node.voteBits, 190 FinalState: node.finalState, 191 Voters: node.voters, 192 FreshStake: node.freshStake, 193 Revocations: node.revocations, 194 PoolSize: node.poolSize, 195 Bits: node.bits, 196 SBits: node.sbits, 197 Height: uint32(node.height), 198 Size: node.blockSize, 199 Timestamp: time.Unix(node.timestamp, 0), 200 Nonce: node.nonce, 201 ExtraData: node.extraData, 202 StakeVersion: node.stakeVersion, 203 } 204 } 205 206 // lotteryIV returns the initialization vector for the deterministic PRNG used 207 // to determine winning tickets. 208 // 209 // This function is safe for concurrent access. 210 func (node *blockNode) lotteryIV() chainhash.Hash { 211 // Serialize the block header for use in calculating the initialization 212 // vector for the ticket lottery. The only way this can fail is if the 213 // process is out of memory in which case it would panic anyways, so 214 // although panics are generally frowned upon in package code, it is 215 // acceptable here. 216 buf := bytes.NewBuffer(make([]byte, 0, wire.MaxBlockHeaderPayload)) 217 header := node.Header() 218 if err := header.Serialize(buf); err != nil { 219 panic(err) 220 } 221 222 return stake.CalcHash256PRNGIV(buf.Bytes()) 223 } 224 225 // populateTicketInfo sets prunable ticket information in the provided block 226 // node. 227 // 228 // This function is NOT safe for concurrent access. It must only be called when 229 // initially creating a node or when protected by the chain lock. 230 func (node *blockNode) populateTicketInfo(spentTickets *stake.SpentTicketsInBlock) { 231 node.ticketsVoted = spentTickets.VotedTickets 232 node.ticketsRevoked = spentTickets.RevokedTickets 233 node.votes = spentTickets.Votes 234 } 235 236 // Ancestor returns the ancestor block node at the provided height by following 237 // the chain backwards from this node. The returned block will be nil when a 238 // height is requested that is after the height of the passed node or is less 239 // than zero. 240 // 241 // This function is safe for concurrent access. 242 func (node *blockNode) Ancestor(height int64) *blockNode { 243 if height < 0 || height > node.height { 244 return nil 245 } 246 247 n := node 248 for ; n != nil && n.height != height; n = n.parent { 249 // Intentionally left blank 250 } 251 252 return n 253 } 254 255 // RelativeAncestor returns the ancestor block node a relative 'distance' blocks 256 // before this node. This is equivalent to calling Ancestor with the node's 257 // height minus provided distance. 258 // 259 // This function is safe for concurrent access. 260 func (node *blockNode) RelativeAncestor(distance int64) *blockNode { 261 return node.Ancestor(node.height - distance) 262 } 263 264 // CalcPastMedianTime calculates the median time of the previous few blocks 265 // prior to, and including, the block node. 266 // 267 // This function is safe for concurrent access. 268 func (node *blockNode) CalcPastMedianTime() time.Time { 269 // Create a slice of the previous few block timestamps used to calculate 270 // the median per the number defined by the constant medianTimeBlocks. 271 timestamps := make([]int64, medianTimeBlocks) 272 numNodes := 0 273 iterNode := node 274 for i := 0; i < medianTimeBlocks && iterNode != nil; i++ { 275 timestamps[i] = iterNode.timestamp 276 numNodes++ 277 278 iterNode = iterNode.parent 279 } 280 281 // Prune the slice to the actual number of available timestamps which 282 // will be fewer than desired near the beginning of the block chain 283 // and sort them. 284 timestamps = timestamps[:numNodes] 285 sort.Sort(timeSorter(timestamps)) 286 287 // NOTE: The consensus rules incorrectly calculate the median for even 288 // numbers of blocks. A true median averages the middle two elements 289 // for a set with an even number of elements in it. Since the constant 290 // for the previous number of blocks to be used is odd, this is only an 291 // issue for a few blocks near the beginning of the chain. I suspect 292 // this is an optimization even though the result is slightly wrong for 293 // a few of the first blocks since after the first few blocks, there 294 // will always be an odd number of blocks in the set per the constant. 295 // 296 // This code follows suit to ensure the same rules are used, however, be 297 // aware that should the medianTimeBlocks constant ever be changed to an 298 // even number, this code will be wrong. 299 medianTimestamp := timestamps[numNodes/2] 300 return time.Unix(medianTimestamp, 0) 301 } 302 303 // blockIndex provides facilities for keeping track of an in-memory index of the 304 // block chain. Although the name block chain suggests a single chain of 305 // blocks, it is actually a tree-shaped structure where any node can have 306 // multiple children. However, there can only be one active branch which does 307 // indeed form a chain from the tip all the way back to the genesis block. 308 type blockIndex struct { 309 // The following fields are set when the instance is created and can't 310 // be changed afterwards, so there is no need to protect them with a 311 // separate mutex. 312 db database.DB 313 314 // These following fields are protected by the embedded mutex. 315 // 316 // index contains an entry for every known block tracked by the block 317 // index. 318 // 319 // modified contains an entry for all nodes that have been modified 320 // since the last time the index was flushed to disk. 321 // 322 // chainTips contains an entry with the tip of all known side chains. 323 sync.RWMutex 324 index map[chainhash.Hash]*blockNode 325 modified map[*blockNode]struct{} 326 chainTips map[int64][]*blockNode 327 } 328 329 // newBlockIndex returns a new empty instance of a block index. The index will 330 // be dynamically populated as block nodes are loaded from the database and 331 // manually added. 332 func newBlockIndex(db database.DB) *blockIndex { 333 return &blockIndex{ 334 db: db, 335 index: make(map[chainhash.Hash]*blockNode), 336 modified: make(map[*blockNode]struct{}), 337 chainTips: make(map[int64][]*blockNode), 338 } 339 } 340 341 // HaveBlock returns whether or not the block index contains the provided hash 342 // and the block data is available. 343 // 344 // This function is safe for concurrent access. 345 func (bi *blockIndex) HaveBlock(hash *chainhash.Hash) bool { 346 bi.RLock() 347 node := bi.index[*hash] 348 hasBlock := node != nil && node.status.HaveData() 349 bi.RUnlock() 350 return hasBlock 351 } 352 353 // addNode adds the provided node to the block index. Duplicate entries are not 354 // checked so it is up to caller to avoid adding them. 355 // 356 // This function MUST be called with the block index lock held (for writes). 357 func (bi *blockIndex) addNode(node *blockNode) { 358 bi.index[node.hash] = node 359 360 // Since the block index does not support nodes that do not connect to 361 // an existing node (except the genesis block), all new nodes are either 362 // extending an existing chain or are on a side chain, but in either 363 // case, are a new chain tip. In the case the node is extending a 364 // chain, the parent is no longer a tip. 365 bi.addChainTip(node) 366 if node.parent != nil { 367 bi.removeChainTip(node.parent) 368 } 369 } 370 371 // AddNode adds the provided node to the block index and marks it as modified. 372 // Duplicate entries are not checked so it is up to caller to avoid adding them. 373 // 374 // This function is safe for concurrent access. 375 func (bi *blockIndex) AddNode(node *blockNode) { 376 bi.Lock() 377 bi.addNode(node) 378 bi.modified[node] = struct{}{} 379 bi.Unlock() 380 } 381 382 // addChainTip adds the passed block node as a new chain tip. 383 // 384 // This function MUST be called with the block index lock held (for writes). 385 func (bi *blockIndex) addChainTip(tip *blockNode) { 386 bi.chainTips[tip.height] = append(bi.chainTips[tip.height], tip) 387 } 388 389 // removeChainTip removes the passed block node from the available chain tips. 390 // 391 // This function MUST be called with the block index lock held (for writes). 392 func (bi *blockIndex) removeChainTip(tip *blockNode) { 393 nodes := bi.chainTips[tip.height] 394 for i, n := range nodes { 395 if n == tip { 396 copy(nodes[i:], nodes[i+1:]) 397 nodes[len(nodes)-1] = nil 398 nodes = nodes[:len(nodes)-1] 399 break 400 } 401 } 402 403 // Either update the map entry for the height with the remaining nodes 404 // or remove it altogether if there are no more nodes left. 405 if len(nodes) == 0 { 406 delete(bi.chainTips, tip.height) 407 } else { 408 bi.chainTips[tip.height] = nodes 409 } 410 } 411 412 // lookupNode returns the block node identified by the provided hash. It will 413 // return nil if there is no entry for the hash. 414 // 415 // This function MUST be called with the block index lock held (for reads). 416 func (bi *blockIndex) lookupNode(hash *chainhash.Hash) *blockNode { 417 return bi.index[*hash] 418 } 419 420 // LookupNode returns the block node identified by the provided hash. It will 421 // return nil if there is no entry for the hash. 422 // 423 // This function is safe for concurrent access. 424 func (bi *blockIndex) LookupNode(hash *chainhash.Hash) *blockNode { 425 bi.RLock() 426 node := bi.lookupNode(hash) 427 bi.RUnlock() 428 return node 429 } 430 431 // NodeStatus returns the status associated with the provided node. 432 // 433 // This function is safe for concurrent access. 434 func (bi *blockIndex) NodeStatus(node *blockNode) blockStatus { 435 bi.RLock() 436 status := node.status 437 bi.RUnlock() 438 return status 439 } 440 441 // SetStatusFlags sets the provided status flags for the given block node 442 // regardless of their previous state. It does not unset any flags. 443 // 444 // This function is safe for concurrent access. 445 func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) { 446 bi.Lock() 447 origStatus := node.status 448 node.status |= flags 449 if node.status != origStatus { 450 bi.modified[node] = struct{}{} 451 } 452 bi.Unlock() 453 } 454 455 // UnsetStatusFlags unsets the provided status flags for the given block node 456 // regardless of their previous state. 457 // 458 // This function is safe for concurrent access. 459 func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) { 460 bi.Lock() 461 origStatus := node.status 462 node.status &^= flags 463 if node.status != origStatus { 464 bi.modified[node] = struct{}{} 465 } 466 bi.Unlock() 467 } 468 469 // flush writes all of the modified block nodes to the database and clears the 470 // set of modified nodes if it succeeds. 471 func (bi *blockIndex) flush() error { 472 // Nothing to flush if there are no modified nodes. 473 bi.Lock() 474 if len(bi.modified) == 0 { 475 bi.Unlock() 476 return nil 477 } 478 479 // Write all of the nodes in the set of modified nodes to the database. 480 err := bi.db.Update(func(dbTx database.Tx) error { 481 for node := range bi.modified { 482 err := dbPutBlockNode(dbTx, node) 483 if err != nil { 484 return err 485 } 486 } 487 return nil 488 }) 489 if err != nil { 490 bi.Unlock() 491 return err 492 } 493 494 // Clear the set of modified nodes. 495 bi.modified = make(map[*blockNode]struct{}) 496 bi.Unlock() 497 return nil 498 }