mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
[NOD-1433] Write specified unit tests for GHOSTDAG (#1010)
commit 3830df34b2a53c361c8a6ca450f7f4a683fe1ae1 Merge: 46dc2e977 17e7819c2 Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 16:29:51 2020 +0200 Merge pull request #1170 from kaspanet/tal-ghost-fix Fix GhostDAG tests and jsons commit 17e7819c27153b8527f18d638a3173a6cc4975eb Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 16:24:01 2020 +0200 Remove non-json ghostdag tests commit 4bebb1d96a8740c5359351c0aea7aca20067d65b Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 13:26:06 2020 +0200 Add a coment above tal's ghostdag2 impl commit faf21a042e0f40f3842bbe2b4a6aeef48a9bf0fd Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 13:20:08 2020 +0200 fix the interfaces after merge commit a8b7a25b2e85a47ef2acffa426db25ce0d8c753c Merge: af91b69b2 f1c6df48c Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 13:19:08 2020 +0200 Merge branch 'v0.8.2-dev' into tal-ghost-fix commit af91b69b207cf3c3e9eaedf031810153b8a576d3 Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 13:18:41 2020 +0200 Fix the non-json tests commit c56f34b73b16f0b28f02f4dc5ae4607b420afb36 Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Tue Dec 1 13:18:17 2020 +0200 Fix the jsons commit 46dc2e97736e304fa5398289566c0d281d02cf8e Author: tal <tal@daglabs.com> Date: Mon Nov 30 17:15:20 2020 +0200 [NOD - 1143] Cosmetics changes. commit b28e5ce816c8f9ea69720b0c8d2e8fb63fc1d6c3 Author: tal <tal@daglabs.com> Date: Mon Nov 30 15:48:08 2020 +0200 [#1126] Place selectedParent to be first on blueMergeSet. commit 4b56ed2da94638736d02c038acaa4ab4d8b625ac Author: tal <tal@daglabs.com> Date: Mon Nov 30 14:51:50 2020 +0200 [#1126] Change pacement between blockRight and blockLeft . commit b09f31be9301cf51a8f3866166cf38a174c368c9 Merge: e17a98b7b 0db39833f Author: talelbaz <63008512+talelbaz@users.noreply.github.com> Date: Mon Nov 30 14:30:22 2020 +0200 Merge pull request #1162 from kaspanet/new-jsons Update the dag json tests commit e17a98b7ba4beba77699fb68081a0d23f4feb714 Author: tal <tal@daglabs.com> Date: Mon Nov 30 14:08:25 2020 +0200 [#1126] Use WALK function in tests & cosmetic changes. commit 0db39833f3afeea8f79a67795d2e532c111b0eda Author: Elichai Turkel <elichai.turkel@gmail.com> Date: Mon Nov 30 12:20:13 2020 +0200 Update the dag json tests commit 5a3da43dd4c492120debabca643293ed5269a842 Author: tal <tal@daglabs.com> Date: Sun Nov 29 12:03:37 2020 +0200 [NOD-1433] Remove unneccessry code. commit a6cde558ac8ff788b548da7ec695460cd680bb32 Author: tal <tal@daglabs.com> Date: Mon Nov 23 17:05:56 2020 +0200 [NOD-1433] Change "Stage" sig function according to the new interface - added error as a return type. commit 07859b6218f503f13079640d1ab9139f9b63a51b Author: tal <tal@daglabs.com> Date: Mon Nov 23 17:03:26 2020 +0200 [NOD-1433] Print formats changed & Cosmetics code changes. commit e1a851664ea69185a93cd189bb328f4cded07a8e Author: tal <tal@daglabs.com> Date: Sun Nov 15 17:34:59 2020 +0200 [NOD-1433] Travers the tests dir and run each test. commit 4c7474edc16ce4553532f893c81f0c795a649b1c Author: tal <tal@daglabs.com> Date: Mon Nov 9 12:44:53 2020 +0200 [NOD-1433] Travers the tests dir and run each test. commit 89dd1e61d36af077493f38d90d925e3057eb962a Author: tal <tal@daglabs.com> Date: Mon Nov 9 11:48:36 2020 +0200 [NOD-1433] Change implementation to adjust genesis's score 0. Also, keep changing the test file to fit the new implementation. commit 6acdcd17def0bb29aca1f65c713d89d1e9960416 Author: tal <tal@daglabs.com> Date: Sun Nov 8 17:07:22 2020 +0200 [NOD-1433] New test was added(Test 6). commit bf238893170e5b5ebc509d40937b410b22d8a9ff Author: tal <tal@daglabs.com> Date: Sun Nov 8 14:59:36 2020 +0200 Fix golint errors commit 79ff990b5f04a5a80ccccd95ec3c6fb745e2ca41 Author: tal <tal@daglabs.com> Date: Sun Nov 8 14:47:12 2020 +0200 added "Optimize imports". commit 73d0128f639517b27a01d016a14d67d7f1a42570 Author: tal <tal@daglabs.com> Date: Sun Nov 8 13:03:22 2020 +0200 Added an implementation factory. commit 61ca8b2e7e20f0dbced5424028e6b52ea511d25c Author: tal <tal@daglabs.com> Date: Thu Nov 5 16:03:18 2020 +0200 1. impl - choose the highest hash. 2. test - changed the test accordingly. commit ef0943ca29ad8699b2c50978cf94d28561bb3e10 Author: tal <tal@daglabs.com> Date: Thu Oct 29 18:00:45 2020 +0200 Update Tests commit 6e5936abff9be604a0bd62329ec2d09be13c1d33 Author: tal <tal@daglabs.com> Date: Tue Oct 27 10:22:45 2020 +0200 Change to the new API commit 5a70dc48b376994634586e0053a56f775b93f6b9 Author: tal <tal@daglabs.com> Date: Mon Oct 26 18:35:31 2020 +0200 1. Added tests for ori commit 2b9f78353f671d2243fee36394618a59f3eb8d4c Author: tal <tal@daglabs.com> Date: Mon Oct 26 13:04:37 2020 +0200 1. Added structure "isolatedTest" {k, test} 2. Added for loop on the tests. 3. New test - Test 5. commit c026d7b7a26348d0f2999a73cb9caefd3ada0ab1 Author: tal <tal@daglabs.com> Date: Thu Oct 22 17:35:56 2020 +0300 Fix bugs in the GHOSTDAG : counters, conntains and isAncestorOf. Added more tests. commit 74493b27d21ed09195eaab164c0f3399312090b5 Author: tal <tal@daglabs.com> Date: Thu Oct 22 16:49:27 2020 +0300 added compare between Hashes commit f689253463cb46cb5787067aade9c7c6545878bc Author: tal <tal@daglabs.com> Date: Thu Oct 22 11:49:01 2020 +0300 added compare between Hashes commit 66be07f6168c8cde92ac68ebbafa45c7ab3484d9 Author: tal <tal@daglabs.com> Date: Mon Oct 19 18:42:40 2020 +0300 First test - pass. commit 327f34f2dcb5567ef983a7d63e857688e5b8a395 Author: tal <tal@daglabs.com> Date: Mon Oct 19 15:20:27 2020 +0300 Add alternative implementation for ghostdag. change all function's signatures (add error type) commit fd2ea3d84a4f21bed0f1e2a4c6eba549287bef46 Author: tal <tal@daglabs.com> Date: Mon Oct 19 11:57:05 2020 +0300 add alternative implementation for ghostdag
This commit is contained in:
parent
f1c6df48c9
commit
21fc2d4219
381
domain/consensus/processes/ghostdag2/ghostdagimpl.go
Normal file
381
domain/consensus/processes/ghostdag2/ghostdagimpl.go
Normal file
@ -0,0 +1,381 @@
|
||||
package ghostdag2
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type ghostdagHelper struct {
|
||||
k model.KType
|
||||
dataStore model.GHOSTDAGDataStore
|
||||
dbAccess model.DBReader
|
||||
dagTopologyManager model.DAGTopologyManager
|
||||
}
|
||||
|
||||
// New creates a new instance of this alternative ghostdag impl
|
||||
func New(
|
||||
databaseContext model.DBReader,
|
||||
dagTopologyManager model.DAGTopologyManager,
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
k model.KType) model.GHOSTDAGManager {
|
||||
|
||||
return &ghostdagHelper{
|
||||
dbAccess: databaseContext,
|
||||
dagTopologyManager: dagTopologyManager,
|
||||
dataStore: ghostdagDataStore,
|
||||
k: k,
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------- */
|
||||
|
||||
func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error {
|
||||
var maxNum uint64 = 0
|
||||
var myScore uint64 = 0
|
||||
/* find the selectedParent */
|
||||
blockParents, err := gh.dagTopologyManager.Parents(blockCandidate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var selectedParent = blockParents[0]
|
||||
for _, parent := range blockParents {
|
||||
blockData, err := gh.dataStore.Get(gh.dbAccess, parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blockScore := blockData.BlueScore
|
||||
if blockScore > maxNum {
|
||||
selectedParent = parent
|
||||
maxNum = blockScore
|
||||
}
|
||||
if blockScore == maxNum && ismoreHash(parent, selectedParent) {
|
||||
selectedParent = parent
|
||||
}
|
||||
}
|
||||
myScore = maxNum
|
||||
|
||||
/* Goal: iterate blockCandidate's mergeSet and divide it to : blue, blues, reds. */
|
||||
var mergeSetBlues = make([]*externalapi.DomainHash, 0)
|
||||
var mergeSetReds = make([]*externalapi.DomainHash, 0)
|
||||
var blueSet = make([]*externalapi.DomainHash, 0)
|
||||
|
||||
mergeSetBlues = append(mergeSetBlues, selectedParent)
|
||||
|
||||
mergeSetArr, err := gh.findMergeSet(blockParents, selectedParent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = gh.sortByBlueScore(mergeSetArr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = gh.findBlueSet(&blueSet, selectedParent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, mergeSetBlock := range mergeSetArr {
|
||||
if *mergeSetBlock == *selectedParent {
|
||||
if !contains(selectedParent, mergeSetBlues) {
|
||||
mergeSetBlues = append(mergeSetBlues, selectedParent)
|
||||
blueSet = append(blueSet, selectedParent)
|
||||
}
|
||||
continue
|
||||
}
|
||||
err := gh.divideBlueRed(selectedParent, mergeSetBlock, &mergeSetBlues, &mergeSetReds, &blueSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
myScore += uint64(len(mergeSetBlues))
|
||||
|
||||
e := model.BlockGHOSTDAGData{
|
||||
BlueScore: myScore,
|
||||
SelectedParent: selectedParent,
|
||||
MergeSetBlues: mergeSetBlues,
|
||||
MergeSetReds: mergeSetReds,
|
||||
}
|
||||
gh.dataStore.Stage(blockCandidate, &e)
|
||||
return nil
|
||||
}
|
||||
|
||||
/* --------isMoreHash(w, selectedParent)----------------*/
|
||||
func ismoreHash(parent *externalapi.DomainHash, selectedParent *externalapi.DomainHash) bool {
|
||||
//Check if parentHash is more then selectedParentHash
|
||||
for i := len(parent) - 1; i >= 0; i-- {
|
||||
switch {
|
||||
case parent[i] < selectedParent[i]:
|
||||
return false
|
||||
case parent[i] > selectedParent[i]:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/* 1. blue = selectedParent.blue + blues
|
||||
2. not connected to at most K blocks (from the blue group)
|
||||
3. for each block at blue , check if not destroy
|
||||
*/
|
||||
|
||||
/* ---------------divideBluesReds--------------------- */
|
||||
func (gh *ghostdagHelper) divideBlueRed(selectedParent *externalapi.DomainHash, desiredBlock *externalapi.DomainHash,
|
||||
blues *[]*externalapi.DomainHash, reds *[]*externalapi.DomainHash, blueSet *[]*externalapi.DomainHash) error {
|
||||
var k = int(gh.k)
|
||||
counter := 0
|
||||
|
||||
var suspectsBlues = make([]*externalapi.DomainHash, 0)
|
||||
isMergeBlue := true
|
||||
//check that not-connected to at most k.
|
||||
for _, block := range *blueSet {
|
||||
isAnticone, err := gh.isAnticone(block, desiredBlock)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isAnticone {
|
||||
counter++
|
||||
suspectsBlues = append(suspectsBlues, block)
|
||||
}
|
||||
if counter > k {
|
||||
isMergeBlue = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isMergeBlue {
|
||||
if !contains(desiredBlock, *reds) {
|
||||
*reds = append(*reds, desiredBlock)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// check that the k-cluster of each blue is still valid.
|
||||
for _, blue := range suspectsBlues {
|
||||
isDestroyed, err := gh.checkIfDestroy(blue, blueSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isDestroyed {
|
||||
isMergeBlue = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isMergeBlue {
|
||||
if !contains(desiredBlock, *reds) {
|
||||
*reds = append(*reds, desiredBlock)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !contains(desiredBlock, *blues) {
|
||||
*blues = append(*blues, desiredBlock)
|
||||
}
|
||||
if !contains(desiredBlock, *blueSet) {
|
||||
*blueSet = append(*blueSet, desiredBlock)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------isAnticone-------------------------- */
|
||||
func (gh *ghostdagHelper) isAnticone(blockA, blockB *externalapi.DomainHash) (bool, error) {
|
||||
isAAncestorOfAB, err := gh.dagTopologyManager.IsAncestorOf(blockA, blockB)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
isBAncestorOfA, err := gh.dagTopologyManager.IsAncestorOf(blockB, blockA)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !isAAncestorOfAB && !isBAncestorOfA, nil
|
||||
|
||||
}
|
||||
|
||||
/* ----------------validateKCluster------------------- */
|
||||
func (gh *ghostdagHelper) validateKCluster(chain *externalapi.DomainHash, checkedBlock *externalapi.DomainHash, counter *int, blueSet *[]*externalapi.DomainHash) (bool, error) {
|
||||
var k = int(gh.k)
|
||||
isAnticone, err := gh.isAnticone(chain, checkedBlock)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if isAnticone {
|
||||
if *counter > k {
|
||||
return false, nil
|
||||
}
|
||||
ifDestroy, err := gh.checkIfDestroy(chain, blueSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if ifDestroy {
|
||||
return false, nil
|
||||
}
|
||||
*counter++
|
||||
return true, nil
|
||||
}
|
||||
isAncestorOf, err := gh.dagTopologyManager.IsAncestorOf(checkedBlock, chain)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if isAncestorOf {
|
||||
dataStore, err := gh.BlockData(chain)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if mergeSetReds := dataStore.MergeSetReds; contains(checkedBlock, mergeSetReds) {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
/*----------------contains-------------------------- */
|
||||
func contains(item *externalapi.DomainHash, items []*externalapi.DomainHash) bool {
|
||||
for _, r := range items {
|
||||
if *r == *item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/* ----------------checkIfDestroy------------------- */
|
||||
/* find number of not-connected in his blue*/
|
||||
func (gh *ghostdagHelper) checkIfDestroy(blockBlue *externalapi.DomainHash, blueSet *[]*externalapi.DomainHash) (bool, error) {
|
||||
// Goal: check that the K-cluster of each block in the blueSet is not destroyed when adding the block to the mergeSet.
|
||||
var k = int(gh.k)
|
||||
counter := 0
|
||||
for _, blue := range *blueSet {
|
||||
isAnticone, err := gh.isAnticone(blue, blockBlue)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if isAnticone {
|
||||
counter++
|
||||
}
|
||||
if counter > k {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
/* ----------------findMergeSet------------------- */
|
||||
func (gh *ghostdagHelper) findMergeSet(parents []*externalapi.DomainHash, selectedParent *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
|
||||
allMergeSet := make([]*externalapi.DomainHash, 0)
|
||||
blockQueue := make([]*externalapi.DomainHash, 0)
|
||||
for _, parent := range parents {
|
||||
if !contains(parent, blockQueue) {
|
||||
blockQueue = append(blockQueue, parent)
|
||||
}
|
||||
|
||||
}
|
||||
for len(blockQueue) > 0 {
|
||||
block := blockQueue[0]
|
||||
blockQueue = blockQueue[1:]
|
||||
if *selectedParent == *block {
|
||||
if !contains(block, allMergeSet) {
|
||||
allMergeSet = append(allMergeSet, block)
|
||||
}
|
||||
continue
|
||||
}
|
||||
isancestorOf, err := gh.dagTopologyManager.IsAncestorOf(block, selectedParent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isancestorOf {
|
||||
continue
|
||||
}
|
||||
if !contains(block, allMergeSet) {
|
||||
allMergeSet = append(allMergeSet, block)
|
||||
}
|
||||
err = gh.insertParent(block, &blockQueue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
return allMergeSet, nil
|
||||
}
|
||||
|
||||
/* ----------------insertParent------------------- */
|
||||
/* Insert all parents to the queue*/
|
||||
func (gh *ghostdagHelper) insertParent(child *externalapi.DomainHash, queue *[]*externalapi.DomainHash) error {
|
||||
parents, err := gh.dagTopologyManager.Parents(child)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, parent := range parents {
|
||||
if contains(parent, *queue) {
|
||||
continue
|
||||
}
|
||||
*queue = append(*queue, parent)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ----------------findBlueSet------------------- */
|
||||
func (gh *ghostdagHelper) findBlueSet(blueSet *[]*externalapi.DomainHash, selectedParent *externalapi.DomainHash) error {
|
||||
for selectedParent != nil {
|
||||
if !contains(selectedParent, *blueSet) {
|
||||
*blueSet = append(*blueSet, selectedParent)
|
||||
}
|
||||
blockData, err := gh.dataStore.Get(gh.dbAccess, selectedParent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mergeSetBlue := blockData.MergeSetBlues
|
||||
for _, blue := range mergeSetBlue {
|
||||
if contains(blue, *blueSet) {
|
||||
continue
|
||||
}
|
||||
*blueSet = append(*blueSet, blue)
|
||||
}
|
||||
selectedParent = blockData.SelectedParent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ----------------sortByBlueScore------------------- */
|
||||
func (gh *ghostdagHelper) sortByBlueScore(arr []*externalapi.DomainHash) error {
|
||||
|
||||
var err error = nil
|
||||
sort.Slice(arr, func(i, j int) bool {
|
||||
|
||||
blockLeft, error := gh.dataStore.Get(gh.dbAccess, arr[i])
|
||||
if error != nil {
|
||||
err = error
|
||||
return false
|
||||
}
|
||||
|
||||
blockRight, error := gh.dataStore.Get(gh.dbAccess, arr[j])
|
||||
if error != nil {
|
||||
err = error
|
||||
return false
|
||||
}
|
||||
|
||||
if blockLeft.BlueScore < blockRight.BlueScore {
|
||||
return true
|
||||
}
|
||||
if blockLeft.BlueScore == blockRight.BlueScore {
|
||||
return ismoreHash(arr[j], arr[i])
|
||||
}
|
||||
return false
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
/* --------------------------------------------- */
|
||||
|
||||
func (gh *ghostdagHelper) BlockData(blockHash *externalapi.DomainHash) (*model.BlockGHOSTDAGData, error) {
|
||||
return gh.dataStore.Get(gh.dbAccess, blockHash)
|
||||
}
|
||||
func (gh *ghostdagHelper) ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (gh *ghostdagHelper) Less(blockHashA *externalapi.DomainHash, ghostdagDataA *model.BlockGHOSTDAGData, blockHashB *externalapi.DomainHash, ghostdagDataB *model.BlockGHOSTDAGData) bool {
|
||||
panic("implement me")
|
||||
}
|
273
domain/consensus/processes/ghostdagmanager/ghostdag_test.go
Normal file
273
domain/consensus/processes/ghostdagmanager/ghostdag_test.go
Normal file
@ -0,0 +1,273 @@
|
||||
package ghostdagmanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdag2"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGHOSTDAG iterates over several dag simulations, and checks
|
||||
// that the blue score, blue set and selected parent of each
|
||||
// block are calculated as expected.
|
||||
func TestGHOSTDAG(t *testing.T) {
|
||||
|
||||
type block struct {
|
||||
ID string `json:"ID"`
|
||||
Score uint64 `json:"ExpectedScore"`
|
||||
SelectedParent string `json:"ExpectedSelectedParent"`
|
||||
MergeSetReds []string `json:"ExpectedReds"`
|
||||
MergeSetBlues []string `json:"ExpectedBlues"`
|
||||
Parents []string `json:"Parents"`
|
||||
}
|
||||
|
||||
// json struct:
|
||||
type testDag struct {
|
||||
K model.KType `json:"K"`
|
||||
GenesisID string `json:"GenesisID"`
|
||||
ExpectedMergeSetReds []string `json:"ExpectedReds"`
|
||||
Blocks []block `json:"Blocks"`
|
||||
}
|
||||
|
||||
type implManager struct {
|
||||
function func(
|
||||
databaseContext model.DBReader,
|
||||
dagTopologyManager model.DAGTopologyManager,
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
k model.KType) model.GHOSTDAGManager
|
||||
implName string
|
||||
}
|
||||
|
||||
dagTopology := &DAGTopologyManagerImpl{
|
||||
parentsMap: make(map[externalapi.DomainHash][]*externalapi.DomainHash),
|
||||
}
|
||||
|
||||
ghostdagDataStore := &GHOSTDAGDataStoreImpl{
|
||||
dagMap: make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData),
|
||||
}
|
||||
var blockGHOSTDAGDataGenesis = &model.BlockGHOSTDAGData{
|
||||
BlueScore: 0,
|
||||
SelectedParent: nil,
|
||||
MergeSetBlues: nil,
|
||||
MergeSetReds: nil,
|
||||
BluesAnticoneSizes: nil,
|
||||
}
|
||||
|
||||
var testsCounter int
|
||||
err := filepath.Walk("../../testdata/dags", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
jsonFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
t.Fatalf("TestGHOSTDAG : failed opening the json file %s: %v", info.Name(), err)
|
||||
}
|
||||
defer jsonFile.Close()
|
||||
var test testDag
|
||||
decoder := json.NewDecoder(jsonFile)
|
||||
decoder.DisallowUnknownFields()
|
||||
err = decoder.Decode(&test)
|
||||
if err != nil {
|
||||
t.Fatalf("TestGHOSTDAG:failed decoding json: %v", err)
|
||||
}
|
||||
|
||||
var genesisHash externalapi.DomainHash
|
||||
copy(genesisHash[:], test.GenesisID)
|
||||
|
||||
dagTopology.parentsMap[genesisHash] = nil
|
||||
|
||||
ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis
|
||||
|
||||
//NOTE: FOR ADDING/REMOVING AN IMPLEMENTATION CHANGE BELOW:
|
||||
implementationFactories := []implManager{
|
||||
{New, "Original"},
|
||||
{ghostdag2.New, "Tal's impl"},
|
||||
}
|
||||
|
||||
for _, factory := range implementationFactories {
|
||||
|
||||
g := factory.function(nil, dagTopology, ghostdagDataStore, model.KType(test.K))
|
||||
for _, testBlockData := range test.Blocks {
|
||||
|
||||
blockID := StringToByte(testBlockData.ID)
|
||||
dagTopology.parentsMap[*blockID] = StringToByteArray(testBlockData.Parents)
|
||||
|
||||
err := g.GHOSTDAG(blockID)
|
||||
if err != nil {
|
||||
t.Fatalf("Test failed: \n Impl: %s,FileName: %s \n error on GHOSTDAG - block %s: %s.",
|
||||
factory.implName, info.Name(), testBlockData.ID, err)
|
||||
}
|
||||
ghostdagData, err := ghostdagDataStore.Get(nil, blockID)
|
||||
if err != nil {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: ghostdagDataStore error: %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, err)
|
||||
}
|
||||
|
||||
if testBlockData.Score != (ghostdagData.BlueScore) {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected blue score %d but got %d.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.Score, ghostdagData.BlueScore)
|
||||
}
|
||||
|
||||
if *StringToByte(testBlockData.SelectedParent) != *ghostdagData.SelectedParent {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected selected parent %v but got %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.SelectedParent, string(ghostdagData.SelectedParent[:]))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetBlues), ghostdagData.MergeSetBlues) {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set blues %v but got %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetBlues, hashesToStrings(ghostdagData.MergeSetBlues))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetReds), ghostdagData.MergeSetReds) {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set reds %v but got %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetReds, hashesToStrings(ghostdagData.MergeSetReds))
|
||||
}
|
||||
|
||||
}
|
||||
dagTopology.parentsMap = make(map[externalapi.DomainHash][]*externalapi.DomainHash)
|
||||
dagTopology.parentsMap[genesisHash] = nil
|
||||
ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData)
|
||||
ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis
|
||||
}
|
||||
|
||||
testsCounter++
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if testsCounter != 3 {
|
||||
t.Fatalf("Expected 3 test files, ran %d instead", testsCounter)
|
||||
}
|
||||
}
|
||||
|
||||
func hashesToStrings(arr []*externalapi.DomainHash) []string {
|
||||
var strArr = make([]string, len(arr))
|
||||
for i, hash := range arr {
|
||||
strArr[i] = string(hash[:])
|
||||
}
|
||||
return strArr
|
||||
}
|
||||
|
||||
func StringToByte(strID string) *externalapi.DomainHash {
|
||||
var domainHash externalapi.DomainHash
|
||||
copy(domainHash[:], strID)
|
||||
return &domainHash
|
||||
}
|
||||
|
||||
func StringToByteArray(stringIDArr []string) []*externalapi.DomainHash {
|
||||
domainHashArr := make([]*externalapi.DomainHash, len(stringIDArr))
|
||||
for i, strID := range stringIDArr {
|
||||
domainHashArr[i] = StringToByte(strID)
|
||||
}
|
||||
return domainHashArr
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
type GHOSTDAGDataStoreImpl struct {
|
||||
dagMap map[externalapi.DomainHash]*model.BlockGHOSTDAGData
|
||||
}
|
||||
|
||||
func (ds *GHOSTDAGDataStoreImpl) Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData *model.BlockGHOSTDAGData) {
|
||||
ds.dagMap[*blockHash] = blockGHOSTDAGData
|
||||
}
|
||||
|
||||
func (ds *GHOSTDAGDataStoreImpl) IsStaged() bool {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (ds *GHOSTDAGDataStoreImpl) Discard() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (ds *GHOSTDAGDataStoreImpl) Commit(dbTx model.DBTransaction) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (ds *GHOSTDAGDataStoreImpl) Get(dbContext model.DBReader, blockHash *externalapi.DomainHash) (*model.BlockGHOSTDAGData, error) {
|
||||
v, ok := ds.dagMap[*blockHash]
|
||||
if ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type DAGTopologyManagerImpl struct {
|
||||
parentsMap map[externalapi.DomainHash][]*externalapi.DomainHash
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) Tips() ([]*externalapi.DomainHash, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) AddTip(tipHash *externalapi.DomainHash) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) Parents(blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
v, ok := dt.parentsMap[*blockHash]
|
||||
if !ok {
|
||||
return []*externalapi.DomainHash{}, nil
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) Children(blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) IsParentOf(hashBlockA *externalapi.DomainHash, hashBlockB *externalapi.DomainHash) (bool, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) IsChildOf(hashBlockA *externalapi.DomainHash, hashBlockB *externalapi.DomainHash) (bool, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) IsAncestorOf(hashBlockA *externalapi.DomainHash, hashBlockB *externalapi.DomainHash) (bool, error) {
|
||||
blockBParents, isOk := dt.parentsMap[*hashBlockB]
|
||||
if !isOk {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, parentOfB := range blockBParents {
|
||||
if *parentOfB == *hashBlockA {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, parentOfB := range blockBParents {
|
||||
isAncestorOf, err := dt.IsAncestorOf(hashBlockA, parentOfB)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if isAncestorOf {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) IsDescendantOf(blockHashA *externalapi.DomainHash, blockHashB *externalapi.DomainHash) (bool, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) IsAncestorOfAny(blockHash *externalapi.DomainHash, potentialDescendants []*externalapi.DomainHash) (bool, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
func (dt *DAGTopologyManagerImpl) IsInSelectedParentChainOf(blockHashA *externalapi.DomainHash, blockHashB *externalapi.DomainHash) (bool, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func (dt *DAGTopologyManagerImpl) SetParents(blockHash *externalapi.DomainHash, parentHashes []*externalapi.DomainHash) error {
|
||||
panic("unimplemented")
|
||||
}
|
252
domain/consensus/testdata/dags/dag0.json
vendored
Normal file
252
domain/consensus/testdata/dags/dag0.json
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
{
|
||||
"K": 4,
|
||||
"GenesisID": "A",
|
||||
"ExpectedReds": [
|
||||
"Q",
|
||||
"H",
|
||||
"I"
|
||||
],
|
||||
"Blocks": [
|
||||
{
|
||||
"ID": "B",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "A",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"A"
|
||||
],
|
||||
"Parents": [
|
||||
"A"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "C",
|
||||
"ExpectedScore": 2,
|
||||
"ExpectedSelectedParent": "B",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"B"
|
||||
],
|
||||
"Parents": [
|
||||
"B"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "D",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "A",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"A"
|
||||
],
|
||||
"Parents": [
|
||||
"A"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "E",
|
||||
"ExpectedScore": 4,
|
||||
"ExpectedSelectedParent": "C",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"C",
|
||||
"D"
|
||||
],
|
||||
"Parents": [
|
||||
"C",
|
||||
"D"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "F",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "A",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"A"
|
||||
],
|
||||
"Parents": [
|
||||
"A"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "G",
|
||||
"ExpectedScore": 2,
|
||||
"ExpectedSelectedParent": "F",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"F"
|
||||
],
|
||||
"Parents": [
|
||||
"F"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "H",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "A",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"A"
|
||||
],
|
||||
"Parents": [
|
||||
"A"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "I",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "A",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"A"
|
||||
],
|
||||
"Parents": [
|
||||
"A"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "J",
|
||||
"ExpectedScore": 7,
|
||||
"ExpectedSelectedParent": "E",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"E",
|
||||
"F",
|
||||
"G"
|
||||
],
|
||||
"Parents": [
|
||||
"E",
|
||||
"G"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "K",
|
||||
"ExpectedScore": 8,
|
||||
"ExpectedSelectedParent": "J",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"J"
|
||||
],
|
||||
"Parents": [
|
||||
"J"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "L",
|
||||
"ExpectedScore": 9,
|
||||
"ExpectedSelectedParent": "K",
|
||||
"ExpectedReds": ["I"],
|
||||
"ExpectedBlues": [
|
||||
"K"
|
||||
],
|
||||
"Parents": [
|
||||
"I",
|
||||
"K"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "M",
|
||||
"ExpectedScore": 10,
|
||||
"ExpectedSelectedParent": "L",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"L"
|
||||
],
|
||||
"Parents": [
|
||||
"L"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "N",
|
||||
"ExpectedScore": 11,
|
||||
"ExpectedSelectedParent": "M",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"M"
|
||||
],
|
||||
"Parents": [
|
||||
"M"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "O",
|
||||
"ExpectedScore": 11,
|
||||
"ExpectedSelectedParent": "M",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"M"
|
||||
],
|
||||
"Parents": [
|
||||
"M"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "2",
|
||||
"ExpectedScore": 11,
|
||||
"ExpectedSelectedParent": "M",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"M"
|
||||
],
|
||||
"Parents": [
|
||||
"M"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "Q",
|
||||
"ExpectedScore": 11,
|
||||
"ExpectedSelectedParent": "M",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"M"
|
||||
],
|
||||
"Parents": [
|
||||
"M"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "R",
|
||||
"ExpectedScore": 11,
|
||||
"ExpectedSelectedParent": "M",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"M"
|
||||
],
|
||||
"Parents": [
|
||||
"M"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "S",
|
||||
"ExpectedScore": 12,
|
||||
"ExpectedSelectedParent": "R",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"R"
|
||||
],
|
||||
"Parents": [
|
||||
"R"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "T",
|
||||
"ExpectedScore": 16,
|
||||
"ExpectedSelectedParent": "S",
|
||||
"ExpectedReds": ["Q"],
|
||||
"ExpectedBlues": [
|
||||
"S",
|
||||
"2",
|
||||
"N",
|
||||
"O"
|
||||
],
|
||||
"Parents": [
|
||||
"N",
|
||||
"O",
|
||||
"2",
|
||||
"Q",
|
||||
"S"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
436
domain/consensus/testdata/dags/dag1.json
vendored
Normal file
436
domain/consensus/testdata/dags/dag1.json
vendored
Normal file
@ -0,0 +1,436 @@
|
||||
{
|
||||
"K": 4,
|
||||
"GenesisID": "0",
|
||||
"Blocks": [
|
||||
{
|
||||
"ID": "1111",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "0",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"0"
|
||||
],
|
||||
"Parents": [
|
||||
"0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "2",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "0",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"0"
|
||||
],
|
||||
"Parents": [
|
||||
"0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "3",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "0",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"0"
|
||||
],
|
||||
"Parents": [
|
||||
"0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "4",
|
||||
"ExpectedScore": 2,
|
||||
"ExpectedSelectedParent": "1111",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"1111"
|
||||
],
|
||||
"Parents": [
|
||||
"1111"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "5",
|
||||
"ExpectedScore": 3,
|
||||
"ExpectedSelectedParent": "3",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"3",
|
||||
"2"
|
||||
],
|
||||
"Parents": [
|
||||
"2",
|
||||
"3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "6",
|
||||
"ExpectedScore": 2,
|
||||
"ExpectedSelectedParent": "3",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"3"
|
||||
],
|
||||
"Parents": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "7",
|
||||
"ExpectedScore": 3,
|
||||
"ExpectedSelectedParent": "6",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"6"
|
||||
],
|
||||
"Parents": [
|
||||
"6"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "8",
|
||||
"ExpectedScore": 3,
|
||||
"ExpectedSelectedParent": "1111",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"1111",
|
||||
"2"
|
||||
],
|
||||
"Parents": [
|
||||
"1111",
|
||||
"2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "9",
|
||||
"ExpectedScore": 5,
|
||||
"ExpectedSelectedParent": "5",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"5",
|
||||
"6"
|
||||
],
|
||||
"Parents": [
|
||||
"5",
|
||||
"6"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "10",
|
||||
"ExpectedScore": 5,
|
||||
"ExpectedSelectedParent": "8",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"8",
|
||||
"4"
|
||||
],
|
||||
"Parents": [
|
||||
"8",
|
||||
"4"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "11",
|
||||
"ExpectedScore": 7,
|
||||
"ExpectedSelectedParent": "9",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"9",
|
||||
"7"
|
||||
],
|
||||
"Parents": [
|
||||
"7",
|
||||
"9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "12",
|
||||
"ExpectedScore": 8,
|
||||
"ExpectedSelectedParent": "10",
|
||||
"ExpectedReds": [
|
||||
"3",
|
||||
"6"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"10",
|
||||
"5",
|
||||
"9"
|
||||
],
|
||||
"Parents": [
|
||||
"10",
|
||||
"9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "13",
|
||||
"ExpectedScore": 6,
|
||||
"ExpectedSelectedParent": "8",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"8",
|
||||
"3",
|
||||
"5"
|
||||
],
|
||||
"Parents": [
|
||||
"5",
|
||||
"8"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "14",
|
||||
"ExpectedScore": 8,
|
||||
"ExpectedSelectedParent": "13",
|
||||
"ExpectedReds": [
|
||||
"4"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"13",
|
||||
"10"
|
||||
],
|
||||
"Parents": [
|
||||
"13",
|
||||
"10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "15",
|
||||
"ExpectedScore": 9,
|
||||
"ExpectedSelectedParent": "11",
|
||||
"ExpectedReds": [
|
||||
"1111",
|
||||
"8"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"11",
|
||||
"13"
|
||||
],
|
||||
"Parents": [
|
||||
"11",
|
||||
"13"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "16",
|
||||
"ExpectedScore": 8,
|
||||
"ExpectedSelectedParent": "11",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"11"
|
||||
],
|
||||
"Parents": [
|
||||
"11"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "17",
|
||||
"ExpectedScore": 9,
|
||||
"ExpectedSelectedParent": "14",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"14"
|
||||
],
|
||||
"Parents": [
|
||||
"14"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "18",
|
||||
"ExpectedScore": 7,
|
||||
"ExpectedSelectedParent": "13",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"13"
|
||||
],
|
||||
"Parents": [
|
||||
"13"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "19",
|
||||
"ExpectedScore": 10,
|
||||
"ExpectedSelectedParent": "15",
|
||||
"ExpectedReds": [
|
||||
"18"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"15"
|
||||
],
|
||||
"Parents": [
|
||||
"18",
|
||||
"15"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20",
|
||||
"ExpectedScore": 10,
|
||||
"ExpectedSelectedParent": "17",
|
||||
"ExpectedReds": [
|
||||
"6",
|
||||
"7",
|
||||
"9",
|
||||
"11",
|
||||
"16"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"17"
|
||||
],
|
||||
"Parents": [
|
||||
"16",
|
||||
"17"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "21",
|
||||
"ExpectedScore": 12,
|
||||
"ExpectedSelectedParent": "20",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"20",
|
||||
"18"
|
||||
],
|
||||
"Parents": [
|
||||
"18",
|
||||
"20"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "22",
|
||||
"ExpectedScore": 13,
|
||||
"ExpectedSelectedParent": "21",
|
||||
"ExpectedReds": [
|
||||
"15",
|
||||
"19"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"21"
|
||||
],
|
||||
"Parents": [
|
||||
"19",
|
||||
"21"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "23",
|
||||
"ExpectedScore": 11,
|
||||
"ExpectedSelectedParent": "17",
|
||||
"ExpectedReds": [
|
||||
"6",
|
||||
"9"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"17",
|
||||
"12"
|
||||
],
|
||||
"Parents": [
|
||||
"12",
|
||||
"17"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "24",
|
||||
"ExpectedScore": 13,
|
||||
"ExpectedSelectedParent": "23",
|
||||
"ExpectedReds": [
|
||||
"7",
|
||||
"11",
|
||||
"16"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"23",
|
||||
"20"
|
||||
],
|
||||
"Parents": [
|
||||
"20",
|
||||
"23"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "25555",
|
||||
"ExpectedScore": 13,
|
||||
"ExpectedSelectedParent": "21",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"21"
|
||||
],
|
||||
"Parents": [
|
||||
"21"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "26",
|
||||
"ExpectedScore": 15,
|
||||
"ExpectedSelectedParent": "25555",
|
||||
"ExpectedReds": [
|
||||
"12",
|
||||
"15",
|
||||
"19",
|
||||
"23",
|
||||
"24"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"25555",
|
||||
"22"
|
||||
],
|
||||
"Parents": [
|
||||
"22",
|
||||
"24",
|
||||
"25555"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "27",
|
||||
"ExpectedScore": 9,
|
||||
"ExpectedSelectedParent": "16",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"16"
|
||||
],
|
||||
"Parents": [
|
||||
"16"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "28",
|
||||
"ExpectedScore": 14,
|
||||
"ExpectedSelectedParent": "25555",
|
||||
"ExpectedReds": [
|
||||
"12",
|
||||
"23"
|
||||
],
|
||||
"ExpectedBlues": [
|
||||
"25555"
|
||||
],
|
||||
"Parents": [
|
||||
"23",
|
||||
"25555"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "29",
|
||||
"ExpectedScore": 17,
|
||||
"ExpectedSelectedParent": "26",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"26",
|
||||
"28"
|
||||
],
|
||||
"Parents": [
|
||||
"26",
|
||||
"28"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "30",
|
||||
"ExpectedScore": 10,
|
||||
"ExpectedSelectedParent": "27",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"27"
|
||||
],
|
||||
"Parents": [
|
||||
"27"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
126
domain/consensus/testdata/dags/dag2.json
vendored
Normal file
126
domain/consensus/testdata/dags/dag2.json
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
{
|
||||
"K": 18,
|
||||
"GenesisID": "786",
|
||||
"ExpectedReds": [],
|
||||
"Blocks": [
|
||||
{
|
||||
"ID": "21d",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "786",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"786"
|
||||
],
|
||||
"Parents": [
|
||||
"786"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "6ef",
|
||||
"ExpectedScore": 2,
|
||||
"ExpectedSelectedParent": "21d",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"21d"
|
||||
],
|
||||
"Parents": [
|
||||
"21d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "c98",
|
||||
"ExpectedScore": 3,
|
||||
"ExpectedSelectedParent": "6ef",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"6ef"
|
||||
],
|
||||
"Parents": [
|
||||
"6ef"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "d1c",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "786",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"786"
|
||||
],
|
||||
"Parents": [
|
||||
"786"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "ec9",
|
||||
"ExpectedScore": 5,
|
||||
"ExpectedSelectedParent": "c98",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"c98",
|
||||
"d1c"
|
||||
],
|
||||
"Parents": [
|
||||
"d1c",
|
||||
"c98"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "f154",
|
||||
"ExpectedScore": 1,
|
||||
"ExpectedSelectedParent": "786",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"786"
|
||||
],
|
||||
"Parents": [
|
||||
"786"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "6c7",
|
||||
"ExpectedScore": 4,
|
||||
"ExpectedSelectedParent": "f154",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"f154",
|
||||
"d1c",
|
||||
"21d"
|
||||
],
|
||||
"Parents": [
|
||||
"d1c",
|
||||
"21d",
|
||||
"f154"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "015",
|
||||
"ExpectedScore": 8,
|
||||
"ExpectedSelectedParent": "ec9",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"ec9",
|
||||
"f154",
|
||||
"6c7"
|
||||
],
|
||||
"Parents": [
|
||||
"ec9",
|
||||
"6c7"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "crash",
|
||||
"ExpectedScore": 6,
|
||||
"ExpectedSelectedParent": "6c7",
|
||||
"ExpectedReds": [],
|
||||
"ExpectedBlues": [
|
||||
"6c7",
|
||||
"6ef"
|
||||
],
|
||||
"Parents": [
|
||||
"6ef",
|
||||
"6c7"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user