diff --git a/packages/ledgerstate/ledgerstate.go b/packages/ledgerstate/ledgerstate.go
index 2270c86f1a03b9d641d1643ec0a9bdd2cfdbef45..fd824a19c900d9072eeec64b040e69974bcc4393 100644
--- a/packages/ledgerstate/ledgerstate.go
+++ b/packages/ledgerstate/ledgerstate.go
@@ -36,6 +36,7 @@ func NewLedgerState(storageId string) *LedgerState {
 
 	mainReality := newReality(MAIN_REALITY_ID)
 	mainReality.ledgerState = result
+	mainReality.SetPreferred()
 	result.realities.Store(mainReality).Release()
 
 	return result
@@ -194,8 +195,7 @@ func (ledgerState *LedgerState) GenerateRealityVisualization(pngFilename string)
 				realityNode.Attr("style", "filled")
 				realityNode.Attr("shape", "rect")
 				realityNode.Attr("color", "#9673A6")
-				realityNode.Attr("fillcolor", "#DAE8FC")
-				realityNode.Attr("penwidth", "2.0")
+				realityNode.Attr("fillcolor", "#E1D5E7")
 			} else {
 				realityNode = graph.Node("REALITY\n\n" + strings.Trim(reality.id.String(), "\x00") + " (" + strconv.Itoa(int(reality.GetTransferOutputCount())) + " / " + strconv.Itoa(len(reality.subRealityIds)) + ")")
 				realityNode.Attr("style", "filled")
@@ -204,7 +204,7 @@ func (ledgerState *LedgerState) GenerateRealityVisualization(pngFilename string)
 				realityNode.Attr("fillcolor", "#DAE8FC")
 			}
 
-			if reality.GetLiked() {
+			if reality.IsLiked() {
 				realityNode.Attr("penwidth", "3.0")
 			}
 
@@ -313,12 +313,17 @@ func (ledgerState *LedgerState) AggregateRealities(realityIds ...RealityId) *obj
 		parentConflictRealities := make(map[RealityId]*objectstorage.CachedObject)
 		aggregatedRealityParentIds := make([]RealityId, len(aggregatedRealities))
 
+		aggregatedRealityIsPreferred := true
+
 		counter := 0
 		for aggregatedRealityId, cachedAggregatedReality := range aggregatedRealities {
 			aggregatedRealityParentIds[counter] = aggregatedRealityId
 			counter++
 
 			aggregatedReality := cachedAggregatedReality.Get().(*Reality)
+
+			aggregatedRealityIsPreferred = aggregatedRealityIsPreferred && aggregatedReality.IsPreferred()
+
 			if !aggregatedReality.IsAggregated() {
 				parentConflictRealities[aggregatedRealityId] = cachedAggregatedReality
 			} else {
@@ -334,6 +339,7 @@ func (ledgerState *LedgerState) AggregateRealities(realityIds ...RealityId) *obj
 		if newCachedAggregatedReality, err := ledgerState.realities.ComputeIfAbsent(aggregatedRealityId[:], func(key []byte) (object objectstorage.StorableObject, e error) {
 			aggregatedReality := newReality(aggregatedRealityId, aggregatedRealityParentIds...)
 			aggregatedReality.ledgerState = ledgerState
+			aggregatedReality.SetPreferred(aggregatedRealityIsPreferred)
 
 			for _, parentRealityId := range aggregatedRealityParentIds {
 				ledgerState.GetReality(parentRealityId).Consume(func(object objectstorage.StorableObject) {
@@ -387,6 +393,7 @@ func (ledgerState *LedgerState) Prune() *LedgerState {
 
 	mainReality := newReality(MAIN_REALITY_ID)
 	mainReality.ledgerState = ledgerState
+	mainReality.SetPreferred()
 	ledgerState.realities.Store(mainReality).Release()
 
 	return ledgerState
diff --git a/packages/ledgerstate/ledgerstate_test.go b/packages/ledgerstate/ledgerstate_test.go
index 65b4e9fdc4eb0e69ae7878d1cb6f6f33acf807da..be5cdf81d3f91ae00ae2acb3b83a8d93b6e50f57 100644
--- a/packages/ledgerstate/ledgerstate_test.go
+++ b/packages/ledgerstate/ledgerstate_test.go
@@ -216,11 +216,11 @@ func multiSpend(ledgerState *LedgerState, outputCount int, transferOutputReferen
 func TestAggregateAggregatedRealities(t *testing.T) {
 	ledgerState, transferOutputs := initializeLedgerStateWithBalances(3)
 
-	multiSpend(ledgerState, 1, transferOutputs[0])
 	outputs0 := multiSpend(ledgerState, 2, multiSpend(ledgerState, 1, transferOutputs[0])[0])
+	multiSpend(ledgerState, 1, transferOutputs[0])
 
-	multiSpend(ledgerState, 1, transferOutputs[1])
 	outputs1 := multiSpend(ledgerState, 2, multiSpend(ledgerState, 1, transferOutputs[1])[0])
+	multiSpend(ledgerState, 1, transferOutputs[1])
 
 	multiSpend(ledgerState, 1, transferOutputs[2])
 	outputs2 := multiSpend(ledgerState, 2, multiSpend(ledgerState, 1, transferOutputs[2])[0])
@@ -236,8 +236,8 @@ func TestAggregateAggregatedRealities(t *testing.T) {
 
 	objectstorage.WaitForWritesToFlush()
 
-	fmt.Println(ledgerState.GenerateRealityVisualization("realities1.png"))
-	NewVisualizer(ledgerState).RenderTransferOutputs("outputs1.png")
+	_ = ledgerState.GenerateRealityVisualization("realities1.png")
+	_ = NewVisualizer(ledgerState).RenderTransferOutputs("outputs1.png")
 
 	multiSpend(ledgerState, 2, outputs0[0], outputs1[0])
 
@@ -245,8 +245,8 @@ func TestAggregateAggregatedRealities(t *testing.T) {
 
 	objectstorage.WaitForWritesToFlush()
 
-	ledgerState.GenerateRealityVisualization("realities2.png")
-	NewVisualizer(ledgerState).RenderTransferOutputs("outputs2.png")
+	_ = ledgerState.GenerateRealityVisualization("realities2.png")
+	_ = NewVisualizer(ledgerState).RenderTransferOutputs("outputs2.png")
 }
 
 func TestElevateAggregatedReality(t *testing.T) {
@@ -268,20 +268,20 @@ func TestElevateAggregatedReality(t *testing.T) {
 	spend(ledgerState, doubleSpentOutputs1[1])
 
 	// double spend funds of aggregated reality
-	//spend(ledgerState, spentInput, doubleSpentOutputs2[0])
+	// spend(ledgerState, spentInput, doubleSpentOutputs2[0])
 
 	// spend funds of conflict in aggregated reality further
-	//lastOutputOfAggregatedReality := spend(ledgerState, outputOfAggregatedReality)
+	// lastOutputOfAggregatedReality := spend(ledgerState, outputOfAggregatedReality)
 
-	//spend(ledgerState, lastOutputOfAggregatedReality, doubleSpentOutputs3[1])
+	// spend(ledgerState, lastOutputOfAggregatedReality, doubleSpentOutputs3[1])
 	spend(ledgerState, spend(ledgerState, spend(ledgerState, outputOfAggregatedReality, spend(ledgerState, doubleSpentOutputs3[1]))))
 
 	time.Sleep(1000 * time.Millisecond)
 
 	objectstorage.WaitForWritesToFlush()
 
-	ledgerState.GenerateRealityVisualization("realities.png")
-	NewVisualizer(ledgerState).RenderTransferOutputs("outputs.png")
+	_ = ledgerState.GenerateRealityVisualization("realities.png")
+	_ = NewVisualizer(ledgerState).RenderTransferOutputs("outputs.png")
 }
 
 func TestElevate(t *testing.T) {
diff --git a/packages/ledgerstate/outputs1.png b/packages/ledgerstate/outputs1.png
index fbb292ef06d60e9e6ddf1bf269990516a389fcb7..dfd470d7176c3bbe1ba5a22a683236185ada77c0 100644
Binary files a/packages/ledgerstate/outputs1.png and b/packages/ledgerstate/outputs1.png differ
diff --git a/packages/ledgerstate/outputs2.png b/packages/ledgerstate/outputs2.png
index e179b2b414762ab36539dfaf7cc665670586d5bb..1091bb3948e28c5185f490646c85590d67c257aa 100644
Binary files a/packages/ledgerstate/outputs2.png and b/packages/ledgerstate/outputs2.png differ
diff --git a/packages/ledgerstate/realities1.png b/packages/ledgerstate/realities1.png
index 07550192e27c9ec302e2e8dd01d90c3883fd6141..632f38af62b17e2feb2609e6e40df9b14e7555ab 100644
Binary files a/packages/ledgerstate/realities1.png and b/packages/ledgerstate/realities1.png differ
diff --git a/packages/ledgerstate/realities2.png b/packages/ledgerstate/realities2.png
index f9c9fbd75bff8bbe0a2106a225f2f529ae0c7d0f..51d0e54970a4ad8e61be95e328557918dc07a4cc 100644
Binary files a/packages/ledgerstate/realities2.png and b/packages/ledgerstate/realities2.png differ
diff --git a/packages/ledgerstate/reality.go b/packages/ledgerstate/reality.go
index a1ff45dfcc2302f91cf8f85cbad5de8f03eff5e9..8f8e7501c99b1d5826e7c4fa8e5dedc26150404e 100644
--- a/packages/ledgerstate/reality.go
+++ b/packages/ledgerstate/reality.go
@@ -21,6 +21,8 @@ type Reality struct {
 	conflictIds           ConflictIdSet
 	conflictIdsMutex      sync.RWMutex
 	transferOutputCount   uint32
+	preferred             bool
+	preferredMutex        sync.RWMutex
 	liked                 bool
 	likedMutex            sync.RWMutex
 
@@ -28,6 +30,135 @@ type Reality struct {
 	ledgerState *LedgerState
 }
 
+func (reality *Reality) areParentsLiked() (parentsLiked bool) {
+	parentsLiked = true
+	for _, cachedParentReality := range reality.GetParentRealities() {
+		if parentsLiked {
+			cachedParentReality.Consume(func(object objectstorage.StorableObject) {
+				parentsLiked = parentsLiked && object.(*Reality).IsLiked()
+			})
+		} else {
+			cachedParentReality.Release()
+		}
+	}
+
+	return
+}
+
+func (reality *Reality) propagateLiked() {
+	reality.likedMutex.Lock()
+	reality.liked = true
+	reality.likedMutex.Unlock()
+
+	reality.SetModified()
+
+	for _, cachedSubReality := range reality.GetSubRealities() {
+		if !cachedSubReality.Exists() {
+			cachedSubReality.Release()
+
+			// TODO: SWITCH TO ERR INSTEAD OF PANIC
+			panic("could not load sub reality")
+		}
+
+		cachedSubReality.Consume(func(object objectstorage.StorableObject) {
+			subReality := object.(*Reality)
+
+			subReality.parentRealityIdsMutex.RLock()
+			if len(subReality.parentRealityIds) == 1 && subReality.parentRealityIds.Contains(reality.id) {
+				subReality.parentRealityIdsMutex.RUnlock()
+
+				subReality.propagateLiked()
+			} else {
+				subReality.parentRealityIdsMutex.RUnlock()
+
+				if subReality.areParentsLiked() {
+					subReality.propagateLiked()
+				}
+			}
+		})
+	}
+}
+
+func (reality *Reality) propagateDisliked() {
+	reality.likedMutex.Lock()
+	reality.liked = false
+	reality.likedMutex.Unlock()
+
+	reality.SetModified()
+
+	for _, cachedSubReality := range reality.GetSubRealities() {
+		if !cachedSubReality.Exists() {
+			cachedSubReality.Release()
+
+			// TODO: SWITCH TO ERR INSTEAD OF PANIC
+			panic("could not load sub reality")
+		}
+
+		cachedSubReality.Consume(func(object objectstorage.StorableObject) {
+			subReality := object.(*Reality)
+
+			if subReality.IsLiked() {
+				subReality.propagateDisliked()
+			}
+		})
+	}
+}
+
+func (reality *Reality) GetSubRealities() (subRealities objectstorage.CachedObjects) {
+	reality.subRealityIdsMutex.RLock()
+	subRealities = make(objectstorage.CachedObjects, len(reality.subRealityIds))
+	i := 0
+	for subRealityId := range reality.subRealityIds {
+		subRealities[i] = reality.ledgerState.GetReality(subRealityId)
+
+		i++
+	}
+	reality.subRealityIdsMutex.RUnlock()
+
+	return
+}
+
+func (reality *Reality) SetPreferred(preferred ...bool) (updated bool) {
+	newPreferredValue := len(preferred) == 0 || preferred[0]
+
+	reality.preferredMutex.RLock()
+	if reality.preferred != newPreferredValue {
+		reality.preferredMutex.RUnlock()
+
+		reality.preferredMutex.Lock()
+		if reality.preferred != newPreferredValue {
+			reality.preferred = newPreferredValue
+
+			if newPreferredValue {
+				if reality.areParentsLiked() {
+					reality.propagateLiked()
+				}
+			} else {
+				if reality.IsLiked() {
+					reality.propagateDisliked()
+				}
+			}
+
+			updated = true
+
+			reality.SetModified()
+		}
+		reality.preferredMutex.Unlock()
+	} else {
+		reality.preferredMutex.RUnlock()
+	}
+
+	return
+}
+
+func (reality *Reality) IsPreferred() (preferred bool) {
+	reality.preferredMutex.RLock()
+	preferred = reality.preferred
+	reality.preferredMutex.RUnlock()
+
+	return
+}
+
 // region DONE REVIEWING ///////////////////////////////////////////////////////////////////////////////////////////////
 
 // Creates a new Reality with the given id and parents. It is only used internally and therefore "private".
@@ -45,7 +176,7 @@ func newReality(id RealityId, parentRealities ...RealityId) *Reality {
 	return result
 }
 
-func (reality *Reality) GetLiked() (liked bool) {
+func (reality *Reality) IsLiked() (liked bool) {
 	reality.likedMutex.RLock()
 	liked = reality.liked
 	reality.likedMutex.RUnlock()
@@ -64,6 +195,8 @@ func (reality *Reality) SetLiked(liked ...bool) (likedStatusChanged bool) {
 		if reality.liked != newLikedStatus {
 			reality.liked = newLikedStatus
 
+			likedStatusChanged = true
+
 			reality.SetModified()
 		}
 		reality.likedMutex.Unlock()
@@ -479,7 +612,7 @@ func (reality *Reality) createRealityForPreviouslyUnconflictingConsumers(consume
 		if cachedElevatedReality, realityErr := reality.ledgerState.realities.ComputeIfAbsent(elevatedRealityId[:], func(key []byte) (object objectstorage.StorableObject, e error) {
 			newReality := newReality(elevatedRealityId, reality.id)
 			newReality.ledgerState = reality.ledgerState
-			newReality.SetLiked()
+			newReality.SetPreferred()
 
 			reality.RegisterSubReality(elevatedRealityId)
 
diff --git a/packages/ledgerstate/reality_id_set.go b/packages/ledgerstate/reality_id_set.go
index e202a3064895de39e666cb399e49b1209f96153d..e5c6ce54f93e73e47277342557238018858e2db4 100644
--- a/packages/ledgerstate/reality_id_set.go
+++ b/packages/ledgerstate/reality_id_set.go
@@ -12,6 +12,12 @@ func NewRealityIdSet(realityIds ...RealityId) (realityIdSet RealityIdSet) {
 	return
 }
 
+func (realityIdSet RealityIdSet) Contains(realityId RealityId) bool {
+	_, exists := realityIdSet[realityId]
+
+	return exists
+}
+
 func (realityIdSet RealityIdSet) Add(realityId RealityId) RealityIdSet {
 	realityIdSet[realityId] = void