[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:
Elichai Turkel 2020-12-01 16:54:13 +02:00
parent f1c6df48c9
commit 21fc2d4219
No known key found for this signature in database
GPG Key ID: 9383CDE9E8E66A7F
5 changed files with 1468 additions and 0 deletions

View 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")
}

View 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
View 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
View 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
View 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"
]
}
]
}