比特币全节点Go语言实现BTCD之区块与节点的几个问题

释放双眼,带上耳机,听听看~!

有一本书上写,每个节点要求连接的节点(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%问题。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ 用libcurl库进行http通讯网络编程

2022-1-11 12:36:11

病毒疫情

尹震宇:白衣为甲,一生光荣

2020-9-25 8:36:00

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索