有一本书上写,每个节点要求连接的节点(node)数量至少为5,但是看代码是至少8个,代码如下:
func (cm *ConnManager) Start() { // Already started? if atomic.AddInt32(&cm.start, 1) != 1 { return } log.Trace("Connection manager started") cm.wg.Add(1) go cm.connHandler() // Start all the listeners so long as the caller requested them and // provided a callback to be invoked when connections are accepted. if cm.cfg.OnAccept != nil { for _, listner := range cm.cfg.Listeners { cm.wg.Add(1) go cm.listenHandler(listner) } } for i := atomic.LoadUint64(&cm.connReqCount); i < uint64(cm.cfg.TargetOutbound); i++ { go cm.NewConnReq() } }其中targetOutBound即是要求的数量。
// TargetOutbound is the number of outbound network connections to // maintain. Defaults to 8. TargetOutbound uint32
中位数和本地系统时间差别不超过70分钟,否则会提醒你更新本机的时间。代码:
func (m *medianTime) AddTimeSample(sourceID string, timeVal time.Time) { m.mtx.Lock() defer m.mtx.Unlock() now := time.Unix(time.Now().Unix(), 0) offsetSecs := int64(timeVal.Sub(now).Seconds()) numOffsets := len(m.offsets) if numOffsets == maxMedianTimeEntries && maxMedianTimeEntries > 0 { m.offsets = m.offsets[1:] numOffsets-- } m.offsets = append(m.offsets, offsetSecs) numOffsets++ // Sort the offsets so the median can be obtained as needed later. sortedOffsets := make([]int64, numOffsets) copy(sortedOffsets, m.offsets) sort.Sort(int64Sorter(sortedOffsets)) offsetDuration := time.Duration(offsetSecs) * time.Second log.Debugf("Added time sample of %v (total: %v)", offsetDuration, numOffsets) if math.Abs(float64(median)) < maxAllowedOffsetSecs { m.offsetSecs = median } else { // The median offset of all added time data is larger than the // maximum allowed offset, so don't use an offset. This // effectively limits how far the local clock can be skewed. m.offsetSecs = 0 if !m.invalidTimeChecked { m.invalidTimeChecked = true // Find if any time samples have a time that is close // to the local time. var remoteHasCloseTime bool for _, offset := range sortedOffsets { if math.Abs(float64(offset)) < similarTimeSecs { remoteHasCloseTime = true break } } // Warn if none of the time samples are close. if !remoteHasCloseTime { log.Warnf("Please check your date and time " + "are correct! btcd will not work " + "properly with an invalid time") } } } medianDuration := time.Duration(m.offsetSecs) * time.Second log.Debugf("New time offset: %v", medianDuration) }
if math.Abs(float64(median)) < maxAllowedOffsetSecs {
即是判断时间,
const ( maxAllowedOffsetSecs = 70 * 60 // 1 hour 10 minutes
同时,在接收到新的block时会拒绝时间与自己差距+2小时和-(前11个block时间中位数)的block
这个逻辑在btcd中还未实现
A chain of blocks with each block referencing the block that preceded it. The most-difficult-to-recreate chain is the best block chain.
区块都引用自前一个区块,重新创建最困难的链就是最好的链。简略代码:
func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) { ... if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 { // Log information about how the block is forking the chain. fork := b.bestChain.FindFork(node) if fork.hash.IsEqual(parentHash) { log.Infof("FORK: Block %v forks the chain at height %d"+ "/block %v, but does not cause a reorganize", node.hash, fork.height, fork.hash) } else { log.Infof("EXTEND FORK: Block %v extends a side chain "+ "which forks the chain at height %d/block %v", node.hash, fork.height, fork.hash) } return false, nil } detachNodes, attachNodes := b.getReorganizeNodes(node) // Reorganize the chain. log.Infof("REORGANIZE: Block %v is causing a reorganize.", node.hash) err := b.reorganizeChain(detachNodes, attachNodes) if writeErr := b.index.flushToDB(); writeErr != nil { log.Warnf("Error flushing block index changes to disk: %v", writeErr) } return err == nil, err }
if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 {
这个就是比较工作量,这个节点的worksum是如何计算的呢?如下:
func CalcWork(bits uint32) *big.Int { difficultyNum := CompactToBig(bits) if difficultyNum.Sign() <= 0 { return big.NewInt(0) } // (1 << 256) / (difficultyNum + 1) denominator := new(big.Int).Add(difficultyNum, bigOne) return new(big.Int).Div(oneLsh256, denominator) }
The block chain provides Bitcoin’s public ledger, an ordered and timestamped record of transactions. This system is used to protect against double spending and modification of previous transaction records.
比特币的区块链提供了公开账本,包含有序的带有时间戳的交易记录。每个区块的打包都会对区块交易检查是否存在双花,每个区块都有一个工作量,修改之前的一个交易记录需要大于原来区块的工作量,即51%问题。