Commit 2b1bde25 authored by David Vorick's avatar David Vorick

unexport blocknode

parent 79def327
......@@ -7,42 +7,42 @@ import (
// A BlockNode contains a block and the list of children to the block. Also
// contains some consensus information like which contracts have terminated and
// where there were missed storage proofs.
type BlockNode struct {
Block Block
Parent *BlockNode
Children []*BlockNode
type blockNode struct {
block Block
parent *blockNode
children []*blockNode
Height BlockHeight
Depth Target // Cumulative weight of all parents.
Target Target // Target for next block.
height BlockHeight
depth Target // Cumulative weight of all parents.
target Target // Target for next block.
DiffsGenerated bool
OutputDiffs []OutputDiff
ContractDiffs []ContractDiff
diffsGenerated bool
outputDiffs []OutputDiff
contractDiffs []ContractDiff
}
// childDepth returns the depth that any child node would have.
// childDepth := (1/parentTarget + 1/parentDepth)^-1
func (bn *BlockNode) childDepth() (depth Target) {
cumulativeDifficulty := new(big.Rat).Add(bn.Target.Inverse(), bn.Depth.Inverse())
func (bn *blockNode) childDepth() (depth Target) {
cumulativeDifficulty := new(big.Rat).Add(bn.target.Inverse(), bn.depth.Inverse())
return RatToTarget(new(big.Rat).Inv(cumulativeDifficulty))
}
// setTarget calculates the target for a node and sets the node's target equal
// to the calculated value.
func (node *BlockNode) setTarget() {
func (node *blockNode) setTarget() {
// To calculate the target, we need to compare our timestamp with the
// timestamp of the reference node, which is `TargetWindow` blocks earlier,
// or if the height is less than `TargetWindow`, it's the genesis block.
var i BlockHeight
referenceNode := node
for i = 0; i < TargetWindow && referenceNode.Parent != nil; i++ {
referenceNode = referenceNode.Parent
for i = 0; i < TargetWindow && referenceNode.parent != nil; i++ {
referenceNode = referenceNode.parent
}
// Calculate the amount to adjust the target by dividing the amount of time
// passed by the expected amount of time passed.
timePassed := node.Block.Timestamp - referenceNode.Block.Timestamp
timePassed := node.block.Timestamp - referenceNode.block.Timestamp
expectedTimePassed := BlockFrequency * Timestamp(i)
targetAdjustment := big.NewRat(int64(timePassed), int64(expectedTimePassed))
......@@ -54,28 +54,28 @@ func (node *BlockNode) setTarget() {
}
// Multiply the previous target by the adjustment to get the new target.
parentTarget := node.Parent.Target
parentTarget := node.parent.target
newRatTarget := new(big.Rat).Mul(parentTarget.Rat(), targetAdjustment)
node.Target = RatToTarget(newRatTarget)
node.target = RatToTarget(newRatTarget)
}
// addBlockToTree takes a block and a parent node, and adds a child node to the
// parent containing the block. No validation is done.
func (s *State) addBlockToTree(b Block) (err error) {
parentNode := s.blockMap[b.ParentBlockID]
newNode := &BlockNode{
Block: b,
Parent: parentNode,
newNode := &blockNode{
block: b,
parent: parentNode,
Height: parentNode.Height + 1,
Depth: parentNode.childDepth(),
height: parentNode.height + 1,
depth: parentNode.childDepth(),
}
newNode.setTarget()
// Add the node to the block map and update the list of its parents
// children.
s.blockMap[b.ID()] = newNode
parentNode.Children = append(parentNode.Children, newNode)
parentNode.children = append(parentNode.children, newNode)
if s.heavierFork(newNode) {
err = s.forkBlockchain(newNode)
......
......@@ -66,14 +66,14 @@ func (s *State) handleOrphanBlock(b Block) error {
// earliestChildTimestamp returns the earliest timestamp that a child node
// can have while still being valid. See section 'Timestamp Rules' in
// Consensus.md.
func (bn *BlockNode) earliestChildTimestamp() Timestamp {
func (bn *blockNode) earliestChildTimestamp() Timestamp {
// Get the previous `MedianTimestampWindow` timestamps.
var intTimestamps []int
referenceNode := bn
for i := 0; i < MedianTimestampWindow; i++ {
intTimestamps = append(intTimestamps, int(referenceNode.Block.Timestamp))
if referenceNode.Parent != nil {
referenceNode = referenceNode.Parent
intTimestamps = append(intTimestamps, int(referenceNode.block.Timestamp))
if referenceNode.parent != nil {
referenceNode = referenceNode.parent
}
}
sort.Ints(intTimestamps)
......@@ -87,7 +87,7 @@ func (bn *BlockNode) earliestChildTimestamp() Timestamp {
func (s *State) validHeader(b Block) (err error) {
parent := s.blockMap[b.ParentBlockID]
// Check the id meets the target.
if !b.CheckTarget(parent.Target) {
if !b.CheckTarget(parent.target) {
err = errors.New("block does not meet target")
return
}
......
......@@ -92,7 +92,7 @@ func testEmptyBlock(t *testing.T, s *State) {
// Check that the diffs have been generated, and that they represent the
// actual changes to the state.
if !bn.DiffsGenerated {
if !bn.diffsGenerated {
t.Error("diffs were not generated on the new block")
}
s.invertRecentBlock()
......
......@@ -97,10 +97,10 @@ func (s *State) BlockOutputDiffs(id BlockID) (diffs []OutputDiff, err error) {
err = errors.New("requested an unknown block")
return
}
if !node.DiffsGenerated {
if !node.diffsGenerated {
err = errors.New("diffs have not been generated for the requested block.")
return
}
diffs = node.OutputDiffs
diffs = node.outputDiffs
return
}
......@@ -8,20 +8,20 @@ import (
// State.heavierFork() returns true if the input node is 5% heavier than the
// current node of the ConsensusState.
func (s *State) heavierFork(newNode *BlockNode) bool {
func (s *State) heavierFork(newNode *blockNode) bool {
threshold := new(big.Rat).Mul(s.currentBlockWeight(), SurpassThreshold)
currentCumDiff := s.depth().Inverse()
requiredCumDiff := new(big.Rat).Add(currentCumDiff, threshold)
newNodeCumDiff := newNode.Depth.Inverse()
newNodeCumDiff := newNode.depth.Inverse()
return newNodeCumDiff.Cmp(requiredCumDiff) == 1
}
// backtrackToBlockchain returns a list of nodes that go from the current node
// to the first parent that is in the current blockchain.
func (s *State) backtrackToBlockchain(bn *BlockNode) (nodes []*BlockNode) {
func (s *State) backtrackToBlockchain(bn *blockNode) (nodes []*blockNode) {
nodes = append(nodes, bn)
for s.currentPath[bn.Height] != bn.Block.ID() {
bn = bn.Parent
for s.currentPath[bn.height] != bn.block.ID() {
bn = bn.parent
nodes = append(nodes, bn)
}
return
......@@ -32,30 +32,30 @@ func (s *State) invertRecentBlock() {
// Invert all of the diffs.
direction := false // blockchain is inverting, set direction flag to false.
for _, od := range bn.OutputDiffs {
for _, od := range bn.outputDiffs {
s.commitOutputDiff(od, direction)
}
for _, cd := range bn.ContractDiffs {
for _, cd := range bn.contractDiffs {
s.commitContractDiff(cd, direction)
}
// Update the current path and currentBlockID
delete(s.currentPath, bn.Height)
s.currentBlockID = bn.Parent.Block.ID()
delete(s.currentPath, bn.height)
s.currentBlockID = bn.parent.block.ID()
}
// rewindToNode will rewind blocks until `bn` is the highest block.
func (s *State) rewindToNode(bn *BlockNode) (rewoundNodes []*BlockNode) {
func (s *State) rewindToNode(bn *blockNode) (rewoundNodes []*blockNode) {
// Sanity check - make sure that bn is in the currentPath.
if DEBUG {
if bn.Block.ID() != s.currentPath[bn.Height] {
if bn.block.ID() != s.currentPath[bn.height] {
panic("bad use of rewindToNode")
}
}
// Remove blocks from the ConsensusState until we get to the
// same parent that we are forking from.
for s.currentBlockID != bn.Block.ID() {
for s.currentBlockID != bn.block.ID() {
rewoundNodes = append(rewoundNodes, s.currentBlockNode())
s.invertRecentBlock()
}
......@@ -64,27 +64,27 @@ func (s *State) rewindToNode(bn *BlockNode) (rewoundNodes []*BlockNode) {
// s.integrateBlock() will verify the block and then integrate it into the
// consensus state.
func (s *State) generateAndApplyDiff(bn *BlockNode) (err error) {
func (s *State) generateAndApplyDiff(bn *blockNode) (err error) {
// Sanity check - generate should only be called if the diffs have not yet
// been generated.
if DEBUG {
if bn.DiffsGenerated {
if bn.diffsGenerated {
panic("misuse of generateAndApplyDiff")
}
}
// Sanity check - current node must be the input node's parent.
if DEBUG {
if bn.Parent.Block.ID() != s.currentBlockID {
if bn.parent.block.ID() != s.currentBlockID {
panic("applying a block node when it's not a valid successor")
}
}
// Update the current block and current path.
s.currentBlockID = bn.Block.ID()
s.currentPath[bn.Height] = bn.Block.ID()
s.currentBlockID = bn.block.ID()
s.currentPath[bn.height] = bn.block.ID()
minerSubsidy := CalculateCoinbase(s.height())
for _, txn := range bn.Block.Transactions {
for _, txn := range bn.block.Transactions {
err = s.validTransaction(txn)
if err != nil {
break
......@@ -92,8 +92,8 @@ func (s *State) generateAndApplyDiff(bn *BlockNode) (err error) {
// Apply the transaction to the ConsensusState, adding it to the list of applied transactions.
outputDiffs, contractDiffs := s.applyTransaction(txn)
bn.OutputDiffs = append(bn.OutputDiffs, outputDiffs...)
bn.ContractDiffs = append(bn.ContractDiffs, contractDiffs...)
bn.outputDiffs = append(bn.outputDiffs, outputDiffs...)
bn.contractDiffs = append(bn.contractDiffs, contractDiffs...)
// Add the miner fees to the miner subsidy.
for _, fee := range txn.MinerFees {
......@@ -107,55 +107,55 @@ func (s *State) generateAndApplyDiff(bn *BlockNode) (err error) {
// Perform maintanence on all open contracts.
outputDiffs, contractDiffs := s.applyContractMaintenance()
bn.OutputDiffs = append(bn.OutputDiffs, outputDiffs...)
bn.ContractDiffs = append(bn.ContractDiffs, contractDiffs...)
bn.outputDiffs = append(bn.outputDiffs, outputDiffs...)
bn.contractDiffs = append(bn.contractDiffs, contractDiffs...)
// Add output contianing miner subsidy.
subsidyOutput := Output{
Value: minerSubsidy,
SpendHash: bn.Block.MinerAddress,
SpendHash: bn.block.MinerAddress,
}
subsidyDiff := OutputDiff{
New: true,
ID: bn.Block.SubsidyID(),
ID: bn.block.SubsidyID(),
Output: subsidyOutput,
}
s.unspentOutputs[bn.Block.SubsidyID()] = subsidyOutput
bn.OutputDiffs = append(bn.OutputDiffs, subsidyDiff)
s.unspentOutputs[bn.block.SubsidyID()] = subsidyOutput
bn.outputDiffs = append(bn.outputDiffs, subsidyDiff)
bn.DiffsGenerated = true
bn.diffsGenerated = true
return
}
// invalidateNode() is a recursive function that deletes all of the
// children of a block and puts them on the bad blocks list.
func (s *State) invalidateNode(node *BlockNode) {
for i := range node.Children {
s.invalidateNode(node.Children[i])
func (s *State) invalidateNode(node *blockNode) {
for i := range node.children {
s.invalidateNode(node.children[i])
}
delete(s.blockMap, node.Block.ID())
s.badBlocks[node.Block.ID()] = struct{}{}
delete(s.blockMap, node.block.ID())
s.badBlocks[node.block.ID()] = struct{}{}
}
func (s *State) applyBlockNode(bn *BlockNode) {
func (s *State) applyBlockNode(bn *blockNode) {
// Sanity check - current node must be the input node's parent.
if DEBUG {
if bn.Parent.Block.ID() != s.currentBlockID {
if bn.parent.block.ID() != s.currentBlockID {
panic("applying a block node when it's not a valid successor")
}
}
// Update current id and current path.
s.currentBlockID = bn.Block.ID()
s.currentPath[bn.Height] = bn.Block.ID()
s.currentBlockID = bn.block.ID()
s.currentPath[bn.height] = bn.block.ID()
// Apply all of the diffs.
direction := true // blockchain is going forward, set direction flag to true.
for _, od := range bn.OutputDiffs {
for _, od := range bn.outputDiffs {
s.commitOutputDiff(od, direction)
}
for _, cd := range bn.ContractDiffs {
for _, cd := range bn.contractDiffs {
s.commitContractDiff(cd, direction)
}
}
......@@ -163,7 +163,7 @@ func (s *State) applyBlockNode(bn *BlockNode) {
// forkBlockchain() will go from the current block over to a block on a
// different fork, rewinding and integrating blocks as needed. forkBlockchain()
// will return an error if any of the blocks in the new fork are invalid.
func (s *State) forkBlockchain(newNode *BlockNode) (err error) {
func (s *State) forkBlockchain(newNode *blockNode) (err error) {
// Get the state hash before attempting a fork.
var stateHash hash.Hash
if DEBUG {
......@@ -183,13 +183,13 @@ func (s *State) forkBlockchain(newNode *BlockNode) (err error) {
// again.
//
// The final block in backtrackNodes has already been applied.
var appliedNodes []*BlockNode
var appliedNodes []*blockNode
for i := len(backtrackNodes) - 2; i >= 0; i-- {
appliedNodes = append(appliedNodes, backtrackNodes[i])
// If the diffs for this node have already been generated, apply them
// directly instead of generating them.
if backtrackNodes[i].DiffsGenerated {
if backtrackNodes[i].diffsGenerated {
s.applyBlockNode(backtrackNodes[i])
continue
}
......
......@@ -13,30 +13,30 @@ func (s *State) blockAtHeight(height BlockHeight) (b Block, exists bool) {
if !exists {
return
}
b = bn.Block
b = bn.block
return
}
// currentBlockNode returns the node of the most recent block in the
// longest fork.
func (s *State) currentBlockNode() *BlockNode {
func (s *State) currentBlockNode() *blockNode {
return s.blockMap[s.currentBlockID]
}
// CurrentBlockWeight() returns the weight of the current block in the
// heaviest fork.
func (s *State) currentBlockWeight() BlockWeight {
return s.currentBlockNode().Target.Inverse()
return s.currentBlockNode().target.Inverse()
}
// depth returns the depth of the current block of the state.
func (s *State) depth() Target {
return s.currentBlockNode().Depth
return s.currentBlockNode().depth
}
// height returns the current height of the state.
func (s *State) height() BlockHeight {
return s.blockMap[s.currentBlockID].Height
return s.blockMap[s.currentBlockID].height
}
// State.Output returns the Output associated with the id provided for input,
......@@ -83,10 +83,10 @@ func (s *State) stateHash() hash.Hash {
leaves := []hash.Hash{
hash.Hash(s.currentBlockID),
hash.HashObject(s.height()),
hash.HashObject(s.currentBlockNode().Target),
hash.HashObject(s.currentBlockNode().Depth),
hash.HashObject(s.currentBlockNode().target),
hash.HashObject(s.currentBlockNode().depth),
hash.HashObject(s.currentBlockNode().earliestChildTimestamp()),
hash.Hash(s.blockRoot.Block.ID()),
hash.Hash(s.blockRoot.block.ID()),
}
// Add all the blocks in the current path.
......@@ -128,7 +128,7 @@ func (s *State) Block(id BlockID) (b Block, exists bool) {
if !exists {
return
}
b = node.Block
b = node.block
return
}
......@@ -141,7 +141,7 @@ func (s *State) BlockAtHeight(height BlockHeight) (b Block, exists bool) {
if !exists {
return
}
b = bn.Block
b = bn.block
return
}
......@@ -162,7 +162,7 @@ func (s *State) Contract(id ContractID) (fc FileContract, exists bool) {
func (s *State) CurrentBlock() Block {
s.mu.RLock()
defer s.mu.RUnlock()
return s.currentBlockNode().Block
return s.currentBlockNode().block
}
// CurrentTarget returns the target of the next block that needs to be
......@@ -170,7 +170,7 @@ func (s *State) CurrentBlock() Block {
func (s *State) CurrentTarget() Target {
s.mu.RLock()
defer s.mu.RUnlock()
return s.currentBlockNode().Target
return s.currentBlockNode().target
}
// EarliestLegalTimestamp returns the earliest legal timestamp of the next
......@@ -197,7 +197,7 @@ func (s *State) HeightOfBlock(bid BlockID) (height BlockHeight, exists bool) {
if !exists {
return
}
height = bn.Height
height = bn.height
return
}
......
......@@ -19,18 +19,18 @@ func (s *State) BlocksSince(id BlockID) (removedBlocks, addedBlocks []BlockID, e
// Get all the ids from going backwards to the blockchain.
reversedNodes := s.backtrackToBlockchain(node)
height := reversedNodes[len(reversedNodes)-1].Height
height := reversedNodes[len(reversedNodes)-1].height
// Eliminate the last node, which is the pivot node, whose diffs are already
// known.
reversedNodes = reversedNodes[:len(reversedNodes)-1]
for _, reversedNode := range reversedNodes {
removedBlocks = append(removedBlocks, reversedNode.Block.ID())
removedBlocks = append(removedBlocks, reversedNode.block.ID())
}
// Get all the ids going forward from the pivot node.
for _, exists := s.currentPath[height]; exists; height++ {
node := s.blockMap[s.currentPath[height]]
addedBlocks = append(addedBlocks, node.Block.ID())
addedBlocks = append(addedBlocks, node.block.ID())
_, exists = s.currentPath[height+1]
}
......
......@@ -18,15 +18,15 @@ func (s *State) currentPathCheck() {
}
// Check that the CurrentPath entry contains the correct block id.
if currentNode.Block.ID() != id {
currentNodeID := currentNode.Block.ID()
if currentNode.block.ID() != id {
currentNodeID := currentNode.block.ID()
println(i)
fmt.Println(id[:])
fmt.Println(currentNodeID[:])
panic("current path does not have correct id!")
}
currentNode = s.blockMap[currentNode.Block.ParentBlockID]
currentNode = s.blockMap[currentNode.block.ParentBlockID]
// Have to do an awkward break beacuse i is unsigned.
if i == 0 {
......
......@@ -19,7 +19,7 @@ type StateInfo struct {
type State struct {
// The block root operates like a linked list of blocks, forming the
// blocktree.
blockRoot *BlockNode
blockRoot *blockNode
// TODO: explain bad blocks.
//
......@@ -29,7 +29,7 @@ type State struct {
// the parent. The second is necessary for checking if a new block is a
// known orphan.
badBlocks map[BlockID]struct{} // A list of blocks that don't verify.
blockMap map[BlockID]*BlockNode // A list of all blocks in the blocktree.
blockMap map[BlockID]*blockNode // A list of all blocks in the blocktree.
missingParents map[BlockID]map[BlockID]Block // A list of all missing parents and their known children.
// Consensus Variables - the current state of consensus according to the
......@@ -48,7 +48,7 @@ func CreateGenesisState() (s *State) {
// Create a new state and initialize the maps.
s = &State{
badBlocks: make(map[BlockID]struct{}),
blockMap: make(map[BlockID]*BlockNode),
blockMap: make(map[BlockID]*blockNode),
missingParents: make(map[BlockID]map[BlockID]Block),
currentPath: make(map[BlockHeight]BlockID),
openContracts: make(map[ContractID]FileContract),
......@@ -60,10 +60,10 @@ func CreateGenesisState() (s *State) {
Timestamp: GenesisTimestamp,
MinerAddress: GenesisAddress,
}
s.blockRoot = &BlockNode{
Block: genesisBlock,
Target: RootTarget,
Depth: RootDepth,
s.blockRoot = &blockNode{
block: genesisBlock,
target: RootTarget,
depth: RootDepth,
}
s.blockMap[genesisBlock.ID()] = s.blockRoot
......
......@@ -8,7 +8,7 @@ import (
func TestApplyTransaction(t *testing.T) {
// Create a state to which transactions can be applied.
s := CreateGenesisState()
genesisSubsidyID := s.currentBlockNode().Block.SubsidyID()
genesisSubsidyID := s.currentBlockNode().block.SubsidyID()
// Check that the genesis subsidy exists.
_, exists := s.unspentOutputs[genesisSubsidyID]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment