aboutsummaryrefslogtreecommitdiffstats
path: root/simulation
diff options
context:
space:
mode:
Diffstat (limited to 'simulation')
-rw-r--r--simulation/app.go23
-rw-r--r--simulation/block-list.go64
-rw-r--r--simulation/marshaller.go8
-rw-r--r--simulation/peer-server.go53
-rw-r--r--simulation/verification.go260
5 files changed, 0 insertions, 408 deletions
diff --git a/simulation/app.go b/simulation/app.go
index 9f399ce..1a67a01 100644
--- a/simulation/app.go
+++ b/simulation/app.go
@@ -150,29 +150,6 @@ func (a *simApp) PrepareWitness(height uint64) (types.Witness, error) {
return a.latestWitness, nil
}
-// TotalOrderingDelivered is called when blocks are delivered by the total
-// ordering algorithm.
-func (a *simApp) TotalOrderingDelivered(
- blockHashes common.Hashes, mode uint32) {
- fmt.Println("OUTPUT", a.NodeID, mode, blockHashes)
- latencies := []time.Duration{}
- func() {
- a.lock.RLock()
- defer a.lock.RUnlock()
- for _, h := range blockHashes {
- latencies = append(latencies, time.Since(a.blockTimestamps[h][blockEventReceived]))
- }
- }()
- blockList := &BlockList{
- ID: a.DeliverID,
- BlockHash: blockHashes,
- ConfirmLatency: latencies,
- }
- // #nosec G104
- a.netModule.Report(blockList)
- a.DeliverID++
-}
-
// BlockDelivered is called when a block in compaction chain is delivered.
func (a *simApp) BlockDelivered(
blockHash common.Hash, pos types.Position, result types.FinalizationResult) {
diff --git a/simulation/block-list.go b/simulation/block-list.go
deleted file mode 100644
index 9e329a7..0000000
--- a/simulation/block-list.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2018 The dexon-consensus Authors
-// This file is part of the dexon-consensus library.
-//
-// The dexon-consensus library is free software: you can redistribute it
-// and/or modify it under the terms of the GNU Lesser General Public License as
-// published by the Free Software Foundation, either version 3 of the License,
-// or (at your option) any later version.
-//
-// The dexon-consensus library is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the dexon-consensus library. If not, see
-// <http://www.gnu.org/licenses/>.
-
-package simulation
-
-import (
- "time"
-
- "github.com/dexon-foundation/dexon-consensus/common"
-)
-
-// BlockList is the list of blocks from the result of Total Ordering Algorithm.
-type BlockList struct {
- ID int `json:"id"`
- BlockHash common.Hashes `json:"blockhash"`
- ConfirmLatency []time.Duration `json:"confirmlatency"`
- // The index is required by heap.Interface.
- index int
-}
-
-// PendingBlockList is a PrioirtyQueue maintaining the BlockList received
-// before the previous one (based on ID).
-type PendingBlockList []*BlockList
-
-// Len, Less and Swap are implementing heap.Interface
-func (p PendingBlockList) Len() int { return len(p) }
-func (p PendingBlockList) Less(i, j int) bool { return p[i].ID < p[j].ID }
-func (p PendingBlockList) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
- p[i].index = i
- p[j].index = j
-}
-
-// Push item in the Heap.
-func (p *PendingBlockList) Push(x interface{}) {
- n := len(*p)
- item := x.(*BlockList)
- item.index = n
- *p = append(*p, item)
-}
-
-// Pop the element from the Heap.
-func (p *PendingBlockList) Pop() interface{} {
- old := *p
- n := len(old)
- item := old[n-1]
- item.index = -1 // For safety.
- *p = old[0 : n-1]
- return item
-}
diff --git a/simulation/marshaller.go b/simulation/marshaller.go
index 6f8aee4..4d2b511 100644
--- a/simulation/marshaller.go
+++ b/simulation/marshaller.go
@@ -36,12 +36,6 @@ func (m *jsonMarshaller) Unmarshal(
break
}
msg = notif
- case "blocklist":
- var blocks BlockList
- if err = json.Unmarshal(payload, &blocks); err != nil {
- break
- }
- msg = &blocks
case "message":
var m message
if err = json.Unmarshal(payload, &m); err != nil {
@@ -63,8 +57,6 @@ func (m *jsonMarshaller) Marshal(msg interface{}) (
switch msg.(type) {
case serverNotification:
msgType = "server-notif"
- case *BlockList:
- msgType = "blocklist"
case *message:
msgType = "message"
default:
diff --git a/simulation/peer-server.go b/simulation/peer-server.go
index a98c59a..3a925a4 100644
--- a/simulation/peer-server.go
+++ b/simulation/peer-server.go
@@ -19,12 +19,10 @@ package simulation
import (
"context"
- "encoding/json"
"fmt"
"log"
"reflect"
"sort"
- "sync"
"time"
"github.com/dexon-foundation/dexon-consensus/common"
@@ -38,8 +36,6 @@ type PeerServer struct {
peers map[types.NodeID]struct{}
msgChannel chan *test.TransportEnvelope
trans test.TransportServer
- peerTotalOrder PeerTotalOrder
- peerTotalOrderMu sync.Mutex
verifiedLen uint64
cfg *config.Config
ctx context.Context
@@ -53,7 +49,6 @@ func NewPeerServer() *PeerServer {
ctx, cancel := context.WithCancel(context.Background())
return &PeerServer{
peers: make(map[types.NodeID]struct{}),
- peerTotalOrder: make(PeerTotalOrder),
ctx: ctx,
ctxCancel: cancel,
blockEvents: make(map[types.NodeID]map[common.Hash][]time.Time),
@@ -68,36 +63,6 @@ func (p *PeerServer) isNode(nID types.NodeID) bool {
return exist
}
-// handleBlockList is the handler for messages with BlockList as payload.
-func (p *PeerServer) handleBlockList(id types.NodeID, blocks *BlockList) {
- p.peerTotalOrderMu.Lock()
- defer p.peerTotalOrderMu.Unlock()
-
- readyForVerify := p.peerTotalOrder[id].PushBlocks(*blocks)
- if !readyForVerify {
- return
- }
- // Verify the total order result.
- go func(id types.NodeID) {
- p.peerTotalOrderMu.Lock()
- defer p.peerTotalOrderMu.Unlock()
-
- var correct bool
- var length int
- p.peerTotalOrder, correct, length = VerifyTotalOrder(id, p.peerTotalOrder)
- if !correct {
- log.Printf("The result of Total Ordering Algorithm has error.\n")
- }
- p.verifiedLen += uint64(length)
- if p.verifiedLen >= p.cfg.Node.MaxBlock {
- if err := p.trans.Broadcast(
- p.peers, &test.FixedLatencyModel{}, ntfShutdown); err != nil {
- panic(err)
- }
- }
- }(id)
-}
-
// handleMessage is the handler for messages with Message as payload.
func (p *PeerServer) handleMessage(id types.NodeID, m *message) {
switch m.Type {
@@ -107,16 +72,6 @@ func (p *PeerServer) handleMessage(id types.NodeID, m *message) {
if len(p.peers) == 0 {
p.ctxCancel()
}
- case blockTimestamp:
- msgs := []timestampMessage{}
- if err := json.Unmarshal(m.Payload, &msgs); err != nil {
- panic(err)
- }
- for _, msg := range msgs {
- if ok := p.peerTotalOrder[id].PushTimestamp(msg); !ok {
- panic(fmt.Errorf("unable to push timestamp: %v", m))
- }
- }
default:
panic(fmt.Errorf("unknown simulation message type: %v", m))
}
@@ -157,8 +112,6 @@ func (p *PeerServer) mainLoop() {
}
// Handle messages based on their type.
switch val := e.Msg.(type) {
- case *BlockList:
- p.handleBlockList(e.From, val)
case *message:
p.handleMessage(e.From, val)
case *test.BlockEventMessage:
@@ -235,14 +188,8 @@ func (p *PeerServer) Run() {
panic(err)
}
log.Println("Simulation is ready to go with", len(p.peers), "nodes")
- // Initialize total order result cache.
- for id := range p.peers {
- p.peerTotalOrder[id] = NewTotalOrderResult(id)
- }
// Block to handle incoming messages.
p.mainLoop()
- // The simulation is done, clean up.
- LogStatus(p.peerTotalOrder)
if err := p.trans.Close(); err != nil {
log.Printf("Error shutting down peerServer: %v\n", err)
}
diff --git a/simulation/verification.go b/simulation/verification.go
deleted file mode 100644
index a5aad8f..0000000
--- a/simulation/verification.go
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2018 The dexon-consensus Authors
-// This file is part of the dexon-consensus library.
-//
-// The dexon-consensus library is free software: you can redistribute it
-// and/or modify it under the terms of the GNU Lesser General Public License as
-// published by the Free Software Foundation, either version 3 of the License,
-// or (at your option) any later version.
-//
-// The dexon-consensus library is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the dexon-consensus library. If not, see
-// <http://www.gnu.org/licenses/>.
-
-package simulation
-
-import (
- "container/heap"
- "log"
- "math"
- "time"
-
- "github.com/dexon-foundation/dexon-consensus/common"
- "github.com/dexon-foundation/dexon-consensus/core/test"
- "github.com/dexon-foundation/dexon-consensus/core/types"
-)
-
-type timeStamp struct {
- time time.Time
- length int
-}
-
-type totalOrderStatus struct {
- blockReceive []timeStamp
- confirmLatency []time.Duration
- blockSeen map[common.Hash]time.Time
- internalTimestampLatency []time.Duration
- externalTimestampLatency []time.Duration
-}
-
-// TotalOrderResult is the object maintaining peer's result of
-// Total Ordering Algorithm.
-type TotalOrderResult struct {
- nodeID types.NodeID
- hashList common.Hashes
- curID int
- pendingBlockList PendingBlockList
- status totalOrderStatus
-}
-
-// PeerTotalOrder stores the TotalOrderResult of each node.
-type PeerTotalOrder = map[types.NodeID]*TotalOrderResult
-
-// NewTotalOrderResult returns pointer to a a new TotalOrderResult instance.
-func NewTotalOrderResult(nID types.NodeID) *TotalOrderResult {
- totalOrder := &TotalOrderResult{
- nodeID: nID,
- status: totalOrderStatus{
- blockSeen: make(map[common.Hash]time.Time),
- },
- }
- heap.Init(&totalOrder.pendingBlockList)
- return totalOrder
-}
-
-func (totalOrder *TotalOrderResult) processStatus(blocks BlockList) {
- totalOrder.status.blockReceive = append(totalOrder.status.blockReceive,
- timeStamp{
- time: time.Now(),
- length: len(blocks.BlockHash),
- })
- totalOrder.status.confirmLatency = append(totalOrder.status.confirmLatency,
- blocks.ConfirmLatency...)
-}
-
-// PushBlocks push a BlockList into the TotalOrderResult and return true if
-// there are new blocks ready for verification.
-func (totalOrder *TotalOrderResult) PushBlocks(blocks BlockList) (ready bool) {
- totalOrder.processStatus(blocks)
- if blocks.ID != totalOrder.curID {
- heap.Push(&totalOrder.pendingBlockList, &blocks)
- return false
- }
-
- // Append all of the consecutive blockList in the pendingBlockList.
- for {
- totalOrder.hashList = append(totalOrder.hashList, blocks.BlockHash...)
- totalOrder.curID++
- if len(totalOrder.pendingBlockList) == 0 ||
- totalOrder.pendingBlockList[0].ID != totalOrder.curID {
- break
- }
- blocks = *heap.Pop(&totalOrder.pendingBlockList).(*BlockList)
- }
- return true
-}
-
-// PushTimestamp logs the information in the msg.
-func (totalOrder *TotalOrderResult) PushTimestamp(msg timestampMessage) bool {
- pushLatency := func(latency *[]time.Duration, t1, t2 time.Time) {
- *latency = append(*latency, t2.Sub(t1))
- }
- switch msg.Event {
- case blockSeen:
- totalOrder.status.blockSeen[msg.BlockHash] = msg.Timestamp
- case timestampConfirm:
- pushLatency(&totalOrder.status.internalTimestampLatency,
- totalOrder.status.blockSeen[msg.BlockHash], msg.Timestamp)
- case timestampAck:
- if seenTime, exist := totalOrder.status.blockSeen[msg.BlockHash]; exist {
- pushLatency(&totalOrder.status.externalTimestampLatency,
- seenTime, msg.Timestamp)
- }
- default:
- return false
- }
- return true
-}
-
-// CalculateBlocksPerSecond calculates the result using status.blockReceive
-func (totalOrder *TotalOrderResult) CalculateBlocksPerSecond() float64 {
- ts := totalOrder.status.blockReceive
- if len(ts) < 2 {
- return 0
- }
-
- diffTime := ts[len(ts)-1].time.Sub(ts[0].time).Seconds()
- if diffTime == 0 {
- return 0
- }
- totalBlocks := 0
- for _, blocks := range ts {
- // Blocks received at time zero are confirmed beforehand.
- if blocks.time == ts[0].time {
- continue
- }
- totalBlocks += blocks.length
- }
- return float64(totalBlocks) / diffTime
-}
-
-// CalculateAverageConfirmLatency calculates the result using
-// status.confirmLatency
-func (totalOrder *TotalOrderResult) CalculateAverageConfirmLatency() float64 {
- sum := 0.0
- for _, latency := range totalOrder.status.confirmLatency {
- sum += latency.Seconds()
- }
- return sum / float64(len(totalOrder.status.confirmLatency))
-}
-
-// CalculateAverageTimestampLatency calculates the result using
-// status.timestampLatency
-func (totalOrder *TotalOrderResult) CalculateAverageTimestampLatency() (
- internal float64, external float64) {
- for _, latency := range totalOrder.status.internalTimestampLatency {
- internal += latency.Seconds()
- }
- if internal > 0 {
- internal /= float64(len(totalOrder.status.internalTimestampLatency))
- }
- for _, latency := range totalOrder.status.externalTimestampLatency {
- external += latency.Seconds()
- }
- if external > 0 {
- external /= float64(len(totalOrder.status.externalTimestampLatency))
- }
- return
-}
-
-// VerifyTotalOrder verifies if the result of Total Ordering Algorithm
-// returned by all nodes are the same. However, the length of result
-// of each nodes may not be the same, so only the common part is verified.
-func VerifyTotalOrder(id types.NodeID,
- totalOrder PeerTotalOrder) (
- unverifiedMap PeerTotalOrder, correct bool, length int) {
-
- hasError := false
-
- // Get the common length from all nodes.
- length = math.MaxInt32
- for _, peerTotalOrder := range totalOrder {
- if len(peerTotalOrder.hashList) < length {
- length = len(peerTotalOrder.hashList)
- }
- }
-
- // Verify if the order of the blocks are the same by comparing
- // the hash value.
- for i := 0; i < length; i++ {
- hash := totalOrder[id].hashList[i]
- for vid, peerTotalOrder := range totalOrder {
- if peerTotalOrder.hashList[i] != hash {
- log.Printf("[%d] Unexpected hash %v from %v\n", i,
- peerTotalOrder.hashList[i], vid)
- hasError = true
- }
- }
- if hasError {
- log.Printf("[%d] Hash is %v from %v\n", i, hash, id)
- } else {
- log.Printf("Block %v confirmed\n", hash)
- }
- }
-
- // Remove verified block from list.
- if length > 0 {
- for vid := range totalOrder {
- totalOrder[vid].hashList =
- totalOrder[vid].hashList[length:]
- }
- }
- return totalOrder, !hasError, length
-}
-
-// LogStatus prints all the status to log.
-func LogStatus(peerTotalOrder PeerTotalOrder) {
- for nID, totalOrder := range peerTotalOrder {
- log.Printf("[Node %s]\n", nID)
- log.Printf(" BPS: %.6f\n", totalOrder.CalculateBlocksPerSecond())
- log.Printf(" Confirm Latency: %.2fms\n",
- totalOrder.CalculateAverageConfirmLatency()*1000)
- log.Printf(" Confirm Blocks: %v\n", len(totalOrder.status.confirmLatency))
- intLatency, extLatency := totalOrder.CalculateAverageTimestampLatency()
- log.Printf(" Internal Timestamp Latency: %.2fms\n", intLatency*1000)
- log.Printf(" External Timestamp Latency: %.2fms\n", extLatency*1000)
- }
- logOverallLatency(peerTotalOrder)
-}
-
-// logOverallLatency prints overall status related to latency.
-func logOverallLatency(peerTotalOrder PeerTotalOrder) {
- // Let's use brute-force way since the simulation should be done
- // at this moment.
- var (
- overallConfirmLatency []time.Duration
- overallInternalTimestampLatency []time.Duration
- overallExternalTimestampLatency []time.Duration
- )
- for _, totalOrder := range peerTotalOrder {
- overallConfirmLatency = append(
- overallConfirmLatency, totalOrder.status.confirmLatency...)
- overallInternalTimestampLatency = append(
- overallInternalTimestampLatency,
- totalOrder.status.internalTimestampLatency...)
- overallExternalTimestampLatency = append(
- overallExternalTimestampLatency,
- totalOrder.status.externalTimestampLatency...)
- }
- log.Print("[Overall]\n")
- avg, dev := test.CalcLatencyStatistics(overallConfirmLatency)
- log.Printf(" Confirm Latency: %v, dev: %v\n", avg, dev)
- avg, dev = test.CalcLatencyStatistics(overallInternalTimestampLatency)
- log.Printf(" Interal Timestamp Latency: %v, dev: %v\n", avg, dev)
- avg, dev = test.CalcLatencyStatistics(overallExternalTimestampLatency)
- log.Printf(" External Timestamp Latency: %v, dev: %v\n", avg, dev)
-}