state sync improvement

pull/88/head
Minh Doan 6 years ago
parent 676785fa36
commit d35f12b85a
  1. 86
      syncing/syncing.go

@ -3,6 +3,7 @@ package syncing
import ( import (
"bufio" "bufio"
"net" "net"
"reflect"
"sync" "sync"
"time" "time"
@ -40,9 +41,11 @@ func GetStateSync() *StateSync {
// StateSync is the struct that implements StateSyncInterface. // StateSync is the struct that implements StateSyncInterface.
type StateSync struct { type StateSync struct {
peerNumber int peerNumber int
activePeerNumber int activePeerNumber int
syncConfig *SyncConfig blockHeight int
syncConfig *SyncConfig
stateSyncTaskQueue *queue.Queue
} }
// ProcessStateSyncFromPeers used to do state sync. // ProcessStateSyncFromPeers used to do state sync.
@ -94,16 +97,24 @@ func (ss *StateSync) makeConnectionToPeers() {
} }
} }
// StartStateSync starts state sync. // areConsensusHashesEqual chesk if all consensus hashes are equal.
func (ss *StateSync) StartStateSync(peers []p2p.Peer, bc *blockchain.Blockchain) { func (ss *StateSync) areConsensusHashesEqual() bool {
// Create sync config. var fixedPeer *SyncPeerConfig
ss.createSyncConfig(peers) for _, configPeer := range ss.syncConfig.peers {
if configPeer.trusted {
// Make connections to peers. if fixedPeer == nil {
ss.makeConnectionToPeers() fixedPeer = &configPeer
}
if !reflect.DeepEqual(configPeer.blockHashes, fixedPeer) {
return false
}
}
}
return true
}
// Looping to get an array of block hashes from honest nodes. // getConsensusHashes gets all hashes needed to download.
LOOP_HONEST_NODE: func (ss *StateSync) getConsensusHashes() {
for { for {
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(ss.activePeerNumber) wg.Add(ss.activePeerNumber)
@ -132,37 +143,39 @@ LOOP_HONEST_NODE:
peerConfig.blockHashes = blockchainSyncMessage.BlockHashes peerConfig.blockHashes = blockchainSyncMessage.BlockHashes
}(&configPeer) }(&configPeer)
} }
wg.Wait() if ss.areConsensusHashesEqual() {
break
if getConsensus(ss.syncConfig) {
break LOOP_HONEST_NODE
} }
} }
}
taskSyncQueue := queue.New(0) // getConsensusHashes gets all hashes needed to download.
blockSize := 0 func (ss *StateSync) generateStateSyncTaskQueue() {
TASK_LOOP: ss.stateSyncTaskQueue = queue.New(0)
for _, configPeer := range ss.syncConfig.peers { for _, configPeer := range ss.syncConfig.peers {
if configPeer.trusted { if configPeer.trusted {
for id, blockHash := range configPeer.blockHashes { for id, blockHash := range configPeer.blockHashes {
taskSyncQueue.Put(SyncBlockTask{index: id, blockHash: blockHash}) ss.stateSyncTaskQueue.Put(SyncBlockTask{index: id, blockHash: blockHash})
} }
blockSize = len(configPeer.blockHashes) ss.blockHeight = len(configPeer.blockHashes)
break TASK_LOOP
} }
} }
}
// downloadBlocks downloads blocks from state sync task queue.
func (ss *StateSync) downloadBlocks(bc *blockchain.Blockchain) {
// Initialize blockchain // Initialize blockchain
bc.Blocks = make([]*blockchain.Block, blockSize) bc.Blocks = make([]*blockchain.Block, ss.blockHeight)
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(ss.activePeerNumber) wg.Add(int(ss.stateSyncTaskQueue.Len()))
for _, configPeer := range ss.syncConfig.peers { for _, configPeer := range ss.syncConfig.peers {
if configPeer.err != nil { if configPeer.err != nil {
continue continue
} }
go func(peerConfig *SyncPeerConfig, taskSyncQueue *queue.Queue, bc *blockchain.Blockchain) { go func(peerConfig *SyncPeerConfig, stateSyncTaskQueue *queue.Queue, bc *blockchain.Blockchain) {
defer wg.Done() defer wg.Done()
for !taskSyncQueue.Empty() { for !stateSyncTaskQueue.Empty() {
task, err := taskSyncQueue.Poll(1, time.Millisecond) task, err := stateSyncTaskQueue.Poll(1, time.Millisecond)
if err == queue.ErrTimeout { if err == queue.ErrTimeout {
break break
} }
@ -181,11 +194,28 @@ TASK_LOOP:
bc.Blocks[syncTask.index] = block bc.Blocks[syncTask.index] = block
} }
} }
}(&configPeer, taskSyncQueue, bc) }(&configPeer, ss.stateSyncTaskQueue, bc)
} }
wg.Wait() wg.Wait()
} }
// StartStateSync starts state sync.
func (ss *StateSync) StartStateSync(peers []p2p.Peer, bc *blockchain.Blockchain) {
// Creates sync config.
ss.createSyncConfig(peers)
// Makes connections to peers.
ss.makeConnectionToPeers()
// Gets consensus hashes.
ss.getConsensusHashes()
// Generates state-sync task queue.
ss.generateStateSyncTaskQueue()
ss.downloadBlocks(bc)
}
func getConsensus(syncConfig *SyncConfig) bool { func getConsensus(syncConfig *SyncConfig) bool {
return true return true
} }

Loading…
Cancel
Save