aboutsummaryrefslogtreecommitdiffstats
path: root/simulation/verification.go
diff options
context:
space:
mode:
Diffstat (limited to 'simulation/verification.go')
-rw-r--r--simulation/verification.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/simulation/verification.go b/simulation/verification.go
new file mode 100644
index 0000000..b32d719
--- /dev/null
+++ b/simulation/verification.go
@@ -0,0 +1,111 @@
+// Copyright 2018 The dexon-consensus-core Authors
+// This file is part of the dexon-consensus-core library.
+//
+// The dexon-consensus-core 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-core 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-core library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package simulation
+
+import (
+ "container/heap"
+ "log"
+ "math"
+
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/types"
+)
+
+// TotalOrderResult is the object maintaining peer's result of
+// Total Ordering Algorithm.
+type TotalOrderResult struct {
+ hashList common.Hashes
+ curID int
+ pendingBlockList PendingBlockList
+}
+
+// PeerTotalOrder stores the TotalOrderResult of each validator.
+type PeerTotalOrder = map[types.ValidatorID]*TotalOrderResult
+
+// NewTotalOrderResult returns pointer to a a new TotalOrderResult instance.
+func NewTotalOrderResult() *TotalOrderResult {
+ totalOrder := &TotalOrderResult{}
+ heap.Init(&totalOrder.pendingBlockList)
+ return totalOrder
+}
+
+// PushBlocks push a BlockList into the TotalOrderResult and return true if
+// there is new blocks ready for verifiy
+func (totalOrder *TotalOrderResult) PushBlocks(blocks BlockList) (ready bool) {
+ 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
+}
+
+// VerifyTotalOrder verifies if the result of Total Ordering Algorithm
+// returned by all validators are the same. However, the length of result
+// of each validators may not be the same, so only the common part is verified.
+func VerifyTotalOrder(id types.ValidatorID,
+ totalOrder PeerTotalOrder) (
+ unverifiedMap PeerTotalOrder, correct bool) {
+
+ hasError := false
+
+ // Get the common length from all validators.
+ 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
+}