Skip to content

Commit

Permalink
Merge pull request #913 from iotaledger/debug/commitment-mismatch2
Browse files Browse the repository at this point in the history
Debug/commitment mismatch2
  • Loading branch information
hmoog authored Apr 17, 2024
2 parents 3822ac2 + 575416a commit 1fdaac2
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 10 deletions.
8 changes: 8 additions & 0 deletions pkg/protocol/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ type Chain struct {
// IsEvicted contains a flag that indicates whether this chain was evicted.
IsEvicted reactive.Event

// IsSolid contains a flag that indicates whether this chain is solid (has a continuous connection to the root).
IsSolid reactive.Event

// shouldEvict contains a flag that indicates whether this chain should be evicted.
shouldEvict reactive.Event

Expand Down Expand Up @@ -86,6 +89,7 @@ func newChain(chains *Chains) *Chain {
StartEngine: reactive.NewVariable[bool](),
Engine: reactive.NewVariable[*engine.Engine](),
IsEvicted: reactive.NewEvent(),
IsSolid: reactive.NewEvent(),
shouldEvict: reactive.NewEvent(),

chains: chains,
Expand Down Expand Up @@ -201,13 +205,15 @@ func (c *Chain) initLogger() (shutdown func()) {
c.LatestSyncedSlot.LogUpdates(c, log.LevelTrace, "LatestSyncedSlot"),
c.OutOfSyncThreshold.LogUpdates(c, log.LevelTrace, "OutOfSyncThreshold"),
c.ForkingPoint.LogUpdates(c, log.LevelTrace, "ForkingPoint", (*Commitment).LogName),
c.ParentChain.LogUpdates(c, log.LevelTrace, "ParentChain", (*Chain).LogName),
c.LatestCommitment.LogUpdates(c, log.LevelTrace, "LatestCommitment", (*Commitment).LogName),
c.LatestAttestedCommitment.LogUpdates(c, log.LevelTrace, "LatestAttestedCommitment", (*Commitment).LogName),
c.LatestProducedCommitment.LogUpdates(c, log.LevelDebug, "LatestProducedCommitment", (*Commitment).LogName),
c.RequestAttestations.LogUpdates(c, log.LevelTrace, "RequestAttestations"),
c.StartEngine.LogUpdates(c, log.LevelDebug, "StartEngine"),
c.Engine.LogUpdates(c, log.LevelTrace, "Engine", (*engine.Engine).LogName),
c.IsEvicted.LogUpdates(c, log.LevelTrace, "IsEvicted"),
c.IsSolid.LogUpdates(c, log.LevelTrace, "IsSolid"),
c.shouldEvict.LogUpdates(c, log.LevelTrace, "shouldEvict"),

c.Logger.Shutdown,
Expand All @@ -233,6 +239,8 @@ func (c *Chain) initDerivedProperties() (shutdown func()) {
c.deriveShouldEvict(forkingPoint, parentChain),
)
}),

c.IsSolid.InheritFrom(forkingPoint.IsSolid),
)
}),
),
Expand Down
4 changes: 3 additions & 1 deletion pkg/protocol/chains.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,9 @@ func (c *Chains) initChainSwitching() (shutdown func()) {

return lo.BatchReverse(
c.HeaviestClaimedCandidate.WithNonEmptyValue(func(heaviestClaimedCandidate *Chain) (shutdown func()) {
return heaviestClaimedCandidate.RequestAttestations.ToggleValue(true)
return heaviestClaimedCandidate.IsSolid.WithNonEmptyValue(func(_ bool) (teardown func()) {
return heaviestClaimedCandidate.RequestAttestations.ToggleValue(true)
})
}),

c.HeaviestAttestedCandidate.OnUpdate(func(_ *Chain, heaviestAttestedCandidate *Chain) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/protocol/commitment.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ type Commitment struct {
// IsRoot contains a flag indicating if this Commitment is the root of the Chain.
IsRoot reactive.Event

// IsSolid contains a flag indicating if this Commitment is solid (has all the commitments in its past cone until
// the RootCommitment).
IsSolid reactive.Event

// IsAttested contains a flag indicating if we have received attestations for this Commitment.
IsAttested reactive.Event

Expand Down Expand Up @@ -108,6 +112,7 @@ func newCommitment(commitments *Commitments, model *model.Commitment) *Commitmen
CumulativeAttestedWeight: reactive.NewVariable[uint64](),
CumulativeVerifiedWeight: reactive.NewVariable[uint64](),
IsRoot: reactive.NewEvent(),
IsSolid: reactive.NewEvent(),
IsAttested: reactive.NewEvent(),
IsSynced: reactive.NewEvent(),
IsCommittable: reactive.NewEvent(),
Expand Down Expand Up @@ -219,6 +224,7 @@ func (c *Commitment) initLogger() (shutdown func()) {
c.CumulativeAttestedWeight.LogUpdates(c, log.LevelTrace, "CumulativeAttestedWeight"),
c.CumulativeVerifiedWeight.LogUpdates(c, log.LevelTrace, "CumulativeVerifiedWeight"),
c.IsRoot.LogUpdates(c, log.LevelTrace, "IsRoot"),
c.IsSolid.LogUpdates(c, log.LevelTrace, "IsSolid"),
c.IsAttested.LogUpdates(c, log.LevelTrace, "IsAttested"),
c.IsSynced.LogUpdates(c, log.LevelTrace, "IsSynced"),
c.IsCommittable.LogUpdates(c, log.LevelTrace, "IsCommittable"),
Expand All @@ -235,6 +241,7 @@ func (c *Commitment) initDerivedProperties() (shutdown func()) {
return lo.BatchReverse(
// mark commitments that are marked as root as verified
c.IsVerified.InheritFrom(c.IsRoot),
c.IsSolid.InheritFrom(c.IsRoot),

// mark commitments that are marked as verified as attested and synced
c.IsAttested.InheritFrom(c.IsVerified),
Expand Down Expand Up @@ -266,6 +273,8 @@ func (c *Commitment) initDerivedProperties() (shutdown func()) {
}),
)
}),

c.IsSolid.InheritFrom(parent.IsSolid),
)
}),

Expand Down
2 changes: 1 addition & 1 deletion pkg/protocol/engine/accounts/accountsledger/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func (m *Manager) Rollback(targetSlot iotago.SlotIndex) error {
}
}

return nil
return m.accountsTree.Commit()
}

// AddAccount adds a new account to the Account tree, allotting to it the balance on the given output.
Expand Down
2 changes: 1 addition & 1 deletion pkg/protocol/engines.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (e *Engines) ForkAtSlot(slot iotago.SlotIndex) (*engine.Engine, error) {
evictionState.Initialize(latestCommitment.Slot())

blockCache := blocks.New(evictionState, newStorage.Settings().APIProvider())
accountsManager := accountsledger.New(module.New(log.NewLogger(log.WithName("ForkedAccountsLedger"))), newStorage.Settings().APIProvider(), blockCache.Block, newStorage.AccountDiffs, newStorage.Accounts())
accountsManager := accountsledger.New(e.protocol.NewSubModule("ForkedAccountsLedger"), newStorage.Settings().APIProvider(), blockCache.Block, newStorage.AccountDiffs, newStorage.Accounts())

accountsManager.SetLatestCommittedSlot(latestCommitment.Slot())
if err = accountsManager.Rollback(slot); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package performance
import (
"io"

"github.com/iotaledger/hive.go/core/safemath"
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/lo"
"github.com/iotaledger/hive.go/serializer/v2"
Expand Down Expand Up @@ -47,12 +48,15 @@ func (t *Tracker) Export(writer io.WriteSeeker, targetSlotIndex iotago.SlotIndex
timeProvider := t.apiProvider.APIForSlot(targetSlotIndex).TimeProvider()
targetEpoch := timeProvider.EpochFromSlot(targetSlotIndex)

// if the target index is the last slot of the epoch, the epoch was committed
if timeProvider.EpochEnd(targetEpoch) != targetSlotIndex {
targetEpoch--
// if the target index is the last slot of the epoch, the epoch was committed - unless it's epoch 0 to avoid underflow.
if timeProvider.EpochEnd(targetEpoch) != targetSlotIndex && targetEpoch > 0 {
targetEpoch = lo.PanicOnErr(safemath.SafeSub(targetEpoch, 1))
}

if err := t.exportPerformanceFactor(writer, timeProvider.EpochStart(targetEpoch+1), targetSlotIndex); err != nil {
// If targetEpoch==0 then export performance factors from slot 0 to the targetSlotIndex.
// PoolRewards and PoolStats are empty if epoch 0 was not committed yet, so it's not a problem.
// But PerformanceFactors are exported for the ongoing epoch, so for epoch 0 we must make an exception and not add 1 to the targetEpoch.
if err := t.exportPerformanceFactor(writer, timeProvider.EpochStart(targetEpoch+lo.Cond(targetEpoch == 0, iotago.EpochIndex(0), iotago.EpochIndex(1))), targetSlotIndex); err != nil {
return ierrors.Wrap(err, "unable to export performance factor")
}

Expand Down Expand Up @@ -277,8 +281,9 @@ func (t *Tracker) exportPoolRewards(writer io.WriteSeeker, targetEpoch iotago.Ep

if err := stream.WriteCollection(writer, serializer.SeriLengthPrefixTypeAsUint32, func() (int, error) {
var epochCount int

for epoch := targetEpoch; epoch > iotago.EpochIndex(lo.Max(0, int(targetEpoch)-daysInYear)); epoch-- {
// Here underflow will not happen because we will stop iterating for epoch 0, because 0 is not greater than zero.
// Use safemath here anyway to avoid hard to trace problems stemming from an accidental underflow.
for epoch := targetEpoch; epoch > iotago.EpochIndex(lo.Max(0, int(targetEpoch)-daysInYear)); epoch = lo.PanicOnErr(safemath.SafeSub(epoch, 1)) {
rewardsMap, err := t.rewardsMap(epoch)
if err != nil {
return 0, ierrors.Wrapf(err, "unable to get rewards tree for epoch %d", epoch)
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/prunable/bucket_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (b *BucketManager) Get(epoch iotago.EpochIndex, realm kvstore.Realm) (kvsto
return nil, ierrors.WithMessagef(database.ErrEpochPruned, "epoch %d", epoch)
}

kv := b.getDBInstance(epoch).KVStore()
kv := newBucketedKVStore(b, b.getDBInstance(epoch).KVStore())

return lo.PanicOnErr(kv.WithExtendedRealm(realm)), nil
}
Expand Down
131 changes: 131 additions & 0 deletions pkg/storage/prunable/bucketed_kvstore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package prunable

import "github.com/iotaledger/hive.go/kvstore"

type bucketedKVStore struct {
bucketManager *BucketManager
store kvstore.KVStore
}

func newBucketedKVStore(bucketManager *BucketManager, store kvstore.KVStore) *bucketedKVStore {
return &bucketedKVStore{
bucketManager: bucketManager,
store: store,
}
}

func (b *bucketedKVStore) WithRealm(realm kvstore.Realm) (kvstore.KVStore, error) {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

s, err := b.store.WithRealm(realm)
if err != nil {
return nil, err
}

return newBucketedKVStore(b.bucketManager, s), nil
}

func (b *bucketedKVStore) WithExtendedRealm(realm kvstore.Realm) (kvstore.KVStore, error) {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

s, err := b.store.WithExtendedRealm(realm)
if err != nil {
return nil, err
}

return newBucketedKVStore(b.bucketManager, s), nil
}

func (b *bucketedKVStore) Realm() kvstore.Realm {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Realm()
}

func (b *bucketedKVStore) Iterate(prefix kvstore.KeyPrefix, kvConsumerFunc kvstore.IteratorKeyValueConsumerFunc, direction ...kvstore.IterDirection) error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Iterate(prefix, kvConsumerFunc, direction...)
}

func (b *bucketedKVStore) IterateKeys(prefix kvstore.KeyPrefix, consumerFunc kvstore.IteratorKeyConsumerFunc, direction ...kvstore.IterDirection) error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.IterateKeys(prefix, consumerFunc, direction...)
}

func (b *bucketedKVStore) Clear() error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Clear()
}

func (b *bucketedKVStore) Get(key kvstore.Key) (value kvstore.Value, err error) {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Get(key)
}

func (b *bucketedKVStore) Set(key kvstore.Key, value kvstore.Value) error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Set(key, value)
}

func (b *bucketedKVStore) Has(key kvstore.Key) (bool, error) {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Has(key)
}

func (b *bucketedKVStore) Delete(key kvstore.Key) error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Delete(key)
}

func (b *bucketedKVStore) DeletePrefix(prefix kvstore.KeyPrefix) error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.DeletePrefix(prefix)
}

func (b *bucketedKVStore) Flush() error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Flush()
}

func (b *bucketedKVStore) Close() error {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Close()
}

func (b *bucketedKVStore) Batched() (kvstore.BatchedMutations, error) {
b.rLockBucketManager()
defer b.rUnlockBucketManager()

return b.store.Batched()
}

func (b *bucketedKVStore) rLockBucketManager() {
b.bucketManager.mutex.RLock()
}

func (b *bucketedKVStore) rUnlockBucketManager() {
b.bucketManager.mutex.RUnlock()
}
Loading

0 comments on commit 1fdaac2

Please sign in to comment.