有一本书上写,每个节点要求连接的节点(node)数量至少为5,但是看代码是至少8个,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1func (cm *ConnManager) Start() {
2 // Already started?
3 if atomic.AddInt32(&cm.start, 1) != 1 {
4 return
5}
6
7 log.Trace("Connection manager started")
8 cm.wg.Add(1)
9 go cm.connHandler()
10
11 // Start all the listeners so long as the caller requested them and
12 // provided a callback to be invoked when connections are accepted.
13 if cm.cfg.OnAccept != nil {
14 for _, listner := range cm.cfg.Listeners {
15 cm.wg.Add(1)
16 go cm.listenHandler(listner)
17 }
18 }
19
20 for i := atomic.LoadUint64(&cm.connReqCount); i < uint64(cm.cfg.TargetOutbound); i++ {
21 go cm.NewConnReq()
22 }
23}
24
1
2 1其中targetOutBound即是要求的数量。
2
1
2
3
4 1// TargetOutbound is the number of outbound network connections to
2// maintain. Defaults to 8.
3TargetOutbound uint32
4
中位数和本地系统时间差别不超过70分钟,否则会提醒你更新本机的时间。代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 1func (m *medianTime) AddTimeSample(sourceID string, timeVal time.Time) {
2 m.mtx.Lock()
3 defer m.mtx.Unlock()
4
5 now := time.Unix(time.Now().Unix(), 0)
6 offsetSecs := int64(timeVal.Sub(now).Seconds())
7 numOffsets := len(m.offsets)
8 if numOffsets == maxMedianTimeEntries && maxMedianTimeEntries > 0 {
9 m.offsets = m.offsets[1:]
10 numOffsets--
11 }
12 m.offsets = append(m.offsets, offsetSecs)
13 numOffsets++
14
15 // Sort the offsets so the median can be obtained as needed later.
16 sortedOffsets := make([]int64, numOffsets)
17 copy(sortedOffsets, m.offsets)
18 sort.Sort(int64Sorter(sortedOffsets))
19
20 offsetDuration := time.Duration(offsetSecs) * time.Second
21log.Debugf("Added time sample of %v (total: %v)", offsetDuration,
22 numOffsets)
23
24 if math.Abs(float64(median)) < maxAllowedOffsetSecs {
25 m.offsetSecs = median
26 } else {
27 // The median offset of all added time data is larger than the
28 // maximum allowed offset, so don't use an offset. This
29 // effectively limits how far the local clock can be skewed.
30 m.offsetSecs = 0
31
32 if !m.invalidTimeChecked {
33 m.invalidTimeChecked = true
34// Find if any time samples have a time that is close
35 // to the local time.
36 var remoteHasCloseTime bool
37 for _, offset := range sortedOffsets {
38 if math.Abs(float64(offset)) < similarTimeSecs {
39 remoteHasCloseTime = true
40break
41}
42 }
43
44 // Warn if none of the time samples are close.
45 if !remoteHasCloseTime {
46 log.Warnf("Please check your date and time " +
47 "are correct! btcd will not work " +
48 "properly with an invalid time")
49 }
50 }
51 }
52
53 medianDuration := time.Duration(m.offsetSecs) * time.Second
54log.Debugf("New time offset: %v", medianDuration)
55}
56
1
2 1if math.Abs(float64(median)) < maxAllowedOffsetSecs {
2
即是判断时间,
1
2
3 1const (
2 maxAllowedOffsetSecs = 70 * 60 // 1 hour 10 minutes
3
同时,在接收到新的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
.
区块都引用自前一个区块,重新创建最困难的链就是最好的链。简略代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 1func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) {
2 ...
3 if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 {
4 // Log information about how the block is forking the chain.
5 fork := b.bestChain.FindFork(node)
6 if fork.hash.IsEqual(parentHash) {
7 log.Infof("FORK: Block %v forks the chain at height %d"+
8 "/block %v, but does not cause a reorganize",
9 node.hash, fork.height, fork.hash)
10 } else {
11 log.Infof("EXTEND FORK: Block %v extends a side chain "+
12 "which forks the chain at height %d/block %v",
13 node.hash, fork.height, fork.hash)
14 }
15
16 return false, nil
17 }
18
19 detachNodes, attachNodes := b.getReorganizeNodes(node)
20
21 // Reorganize the chain.
22 log.Infof("REORGANIZE: Block %v is causing a reorganize.", node.hash)
23 err := b.reorganizeChain(detachNodes, attachNodes)
24
25 if writeErr := b.index.flushToDB(); writeErr != nil {
26 log.Warnf("Error flushing block index changes to disk: %v", writeErr)
27 }
28
29 return err == nil, err
30}
31
1
2 1if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 {
2
这个就是比较工作量,这个节点的worksum是如何计算的呢?如下:
1
2
3
4
5
6
7
8
9
10
11
12 1func CalcWork(bits uint32) *big.Int {
2
3 difficultyNum := CompactToBig(bits)
4 if difficultyNum.Sign() <= 0 {
5 return big.NewInt(0)
6 }
7
8 // (1 << 256) / (difficultyNum + 1)
9 denominator := new(big.Int).Add(difficultyNum, bigOne)
10 return new(big.Int).Div(oneLsh256, denominator)
11}
12
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%问题。