Skip to content

Commit 7d42ba3

Browse files
authored
Merge pull request #2414 from iotaledger/develop
2 parents 622d1d5 + 623d85b commit 7d42ba3

File tree

22 files changed

+161
-94
lines changed

22 files changed

+161
-94
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# v0.9.6 - 2022-09-01
2+
3+
> This release introduces major bugfixes to epoch notarization and networking.
4+
5+
- Fix: several bugs in Notarization and Networking (#2412)
6+
- Wrap faucet errors and add faucet logging (#2411)
7+
- Fix concurrent map writes in integration network shutdown (#2410)
8+
19
# v0.9.5 - 2022-08-31
210

311
> This release introduces a warpsync plugin for fast epochs retrieval, a simplified faucet, local snapshot improvements, and network and general bug fixes.

deploy/ansible/roles/goshimmer-node/templates/docker-compose-analysis-server.yml.j2

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ services:
2929
--metrics.local=false
3030
--metrics.global=true
3131
--node.enablePlugins=analysisServer,analysisDashboard,prometheus
32-
--node.disablePlugins=activity,analysisClient,chat,consensus,dashboard,faucet,gossip,firewall,issuer,mana,manualpeering,blockLayer,metrics,networkdelay,portcheck,pow,syncBeaconFollower,webAPIBroadcastDataEndpoint,WebAPIDataEndpoint,WebAPIHealthzEndpoint,WebAPIFaucetRequestEndpoint,webAPIFindTransactionHashesEndpoint,webAPIGetNeighborsEndpoint,webAPIGetTransactionObjectsByHashEndpoint,webAPIGetTransactionTrytesByHashEndpoint,WebAPIInfoEndpoint,WebAPILedgerstateEndpoint,WebAPIBlockEndpoint,WebAPIToolsBlockEndpoint,WebAPIWeightProviderEndpoint,remotelog,remotelogmetrics,DAGsVisualizer,WebAPIRateSetterEndpoint,WebAPISchedulerEndpoint,ManaInitializer,Notarization,EpochStorage,WebAPIEpochEndpoint,BootstrapManager
32+
--node.disablePlugins=activity,analysisClient,chat,consensus,dashboard,faucet,gossip,firewall,issuer,mana,manualpeering,blockLayer,metrics,networkdelay,portcheck,pow,syncBeaconFollower,webAPIBroadcastDataEndpoint,WebAPIDataEndpoint,WebAPIHealthzEndpoint,WebAPIFaucetRequestEndpoint,webAPIFindTransactionHashesEndpoint,webAPIGetNeighborsEndpoint,webAPIGetTransactionObjectsByHashEndpoint,webAPIGetTransactionTrytesByHashEndpoint,WebAPIInfoEndpoint,WebAPILedgerstateEndpoint,WebAPIBlockEndpoint,WebAPIToolsBlockEndpoint,WebAPIWeightProviderEndpoint,remotelog,remotelogmetrics,DAGsVisualizer,WebAPIRateSetterEndpoint,WebAPISchedulerEndpoint,ManaInitializer,Notarization,EpochStorage,WebAPIEpochEndpoint,BootstrapManager,Warpsync,Snapshot
3333
--logger.level={{ logLevel }}
3434
--logger.outputPaths=stdout

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ require (
3636
go.uber.org/atomic v1.9.0
3737
go.uber.org/dig v1.15.0
3838
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
39+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
3940
google.golang.org/protobuf v1.28.1
4041
gopkg.in/src-d/go-git.v4 v4.13.1
4142
)
@@ -184,7 +185,6 @@ require (
184185
go.uber.org/multierr v1.8.0 // indirect
185186
go.uber.org/zap v1.22.0 // indirect
186187
golang.org/x/net v0.0.0-20220809012201-f428fae20770 // indirect
187-
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
188188
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664 // indirect
189189
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
190190
golang.org/x/text v0.3.7 // indirect

packages/core/epoch/types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919

2020
var (
2121
// GenesisTime is the time (Unix in seconds) of the genesis.
22-
GenesisTime int64 = 1661859573
22+
GenesisTime int64 = 1662035280
2323
// Duration is the default epoch duration in seconds.
2424
Duration int64 = 10
2525
)

packages/core/mana/events.go

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/iotaledger/hive.go/core/stringify"
1010
"github.com/mr-tron/base58"
1111

12+
"github.com/iotaledger/goshimmer/packages/core/epoch"
13+
"github.com/iotaledger/goshimmer/packages/core/ledger"
1214
"github.com/iotaledger/goshimmer/packages/core/ledger/utxo"
1315
)
1416

@@ -58,6 +60,16 @@ type Event interface {
5860
String() string
5961
}
6062

63+
// ManaVectorUpdateEvent is a container that acts as a dictionary for the EpochCommittable event related parameters.
64+
type ManaVectorUpdateEvent struct {
65+
// EI is the index of committable epoch.
66+
EI epoch.Index
67+
// Spent are outputs that is spent in a transaction.
68+
Spent []*ledger.OutputWithMetadata
69+
// Created are the outputs created in a transaction.
70+
Created []*ledger.OutputWithMetadata
71+
}
72+
6173
// PledgedEvent is the struct that is passed along with triggering a Pledged event.
6274
type PledgedEvent struct {
6375
NodeID identity.ID

packages/core/notarization/commitments.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/iotaledger/hive.go/core/generics/lo"
1616
"github.com/iotaledger/hive.go/core/generics/objectstorage"
17+
"github.com/iotaledger/hive.go/core/generics/shrinkingmap"
1718
"github.com/iotaledger/hive.go/core/kvstore"
1819
"golang.org/x/crypto/blake2b"
1920

@@ -49,7 +50,7 @@ type CommitmentTrees struct {
4950

5051
// EpochCommitmentFactory manages epoch commitmentTrees.
5152
type EpochCommitmentFactory struct {
52-
commitmentTrees map[epoch.Index]*CommitmentTrees
53+
commitmentTrees *shrinkingmap.ShrinkingMap[epoch.Index, *CommitmentTrees]
5354

5455
storage *EpochCommitmentStorage
5556
tangle *tangleold.Tangle
@@ -74,7 +75,7 @@ func NewEpochCommitmentFactory(store kvstore.KVStore, tangle *tangleold.Tangle,
7475
manaRootTreeValueStore := objectstorage.NewStoreWithRealm(epochCommitmentStorage.baseStore, database.PrefixNotarization, prefixManaTreeValues)
7576

7677
return &EpochCommitmentFactory{
77-
commitmentTrees: make(map[epoch.Index]*CommitmentTrees),
78+
commitmentTrees: shrinkingmap.New[epoch.Index, *CommitmentTrees](),
7879
storage: epochCommitmentStorage,
7980
tangle: tangle,
8081
snapshotDepth: snapshotDepth,
@@ -344,7 +345,10 @@ func (f *EpochCommitmentFactory) newEpochRoots(ei epoch.Index) (commitmentRoots
344345
}
345346

346347
// We advance the LedgerState to the next epoch.
347-
f.commitLedgerState(ei - epoch.Index(f.snapshotDepth))
348+
epochToCommit := ei - epoch.Index(f.snapshotDepth)
349+
if epochToCommit > 0 {
350+
f.commitLedgerState(epochToCommit)
351+
}
348352

349353
commitmentRoots = &epoch.CommitmentRoots{
350354
StateRoot: epoch.NewMerkleRoot(stateRoot),
@@ -354,7 +358,7 @@ func (f *EpochCommitmentFactory) newEpochRoots(ei epoch.Index) (commitmentRoots
354358
}
355359

356360
// We are never going to use this epoch's commitment trees again.
357-
delete(f.commitmentTrees, ei)
361+
f.commitmentTrees.Delete(ei)
358362

359363
return commitmentRoots, nil
360364
}
@@ -383,10 +387,10 @@ func (f *EpochCommitmentFactory) getCommitmentTrees(ei epoch.Index) (commitmentT
383387
if ei <= lastCommittedEpoch {
384388
return nil, errors.Errorf("cannot get commitment trees for epoch %d, because it is already committed", ei)
385389
}
386-
commitmentTrees, ok := f.commitmentTrees[ei]
390+
commitmentTrees, ok := f.commitmentTrees.Get(ei)
387391
if !ok {
388392
commitmentTrees = f.newCommitmentTrees(ei)
389-
f.commitmentTrees[ei] = commitmentTrees
393+
f.commitmentTrees.Set(ei, commitmentTrees)
390394
}
391395
return
392396
}

packages/core/notarization/events.go

+4-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/iotaledger/goshimmer/packages/core/epoch"
55
"github.com/iotaledger/goshimmer/packages/core/ledger"
66
"github.com/iotaledger/goshimmer/packages/core/ledger/utxo"
7+
"github.com/iotaledger/goshimmer/packages/core/mana"
78
"github.com/iotaledger/goshimmer/packages/core/tangleold"
89
"github.com/iotaledger/hive.go/core/generics/event"
910
"github.com/iotaledger/hive.go/core/identity"
@@ -20,7 +21,7 @@ type Events struct {
2021
// CompetingCommitmentDetected is an event that gets triggered whenever a competing epoch commitment is detected.
2122
CompetingCommitmentDetected *event.Event[*CompetingCommitmentDetectedEvent]
2223
// ManaVectorUpdate is an event that gets triggered whenever the consensus mana vector needs to be updated.
23-
ManaVectorUpdate *event.Event[*ManaVectorUpdateEvent]
24+
ManaVectorUpdate *event.Event[*mana.ManaVectorUpdateEvent]
2425
// TangleTreeInserted is an event that gets triggered when a Block is inserted into the Tangle smt.
2526
TangleTreeInserted *event.Event[*TangleTreeUpdatedEvent]
2627
// TangleTreeRemoved is an event that gets triggered when a Block is removed from Tangle smt.
@@ -69,10 +70,10 @@ type StateMutationTreeUpdatedEvent struct {
6970
type UTXOUpdatedEvent struct {
7071
// EI is the index of updated UTXO.
7172
EI epoch.Index
72-
// Created are the outputs created in a transaction.
73-
Created []*ledger.OutputWithMetadata
7473
// Spent are outputs that is spent in a transaction.
7574
Spent []*ledger.OutputWithMetadata
75+
// Created are the outputs created in a transaction.
76+
Created []*ledger.OutputWithMetadata
7677
}
7778

7879
// EpochCommittableEvent is a container that acts as a dictionary for the EpochCommittable event related parameters.
@@ -95,12 +96,6 @@ type CompetingCommitmentDetectedEvent struct {
9596
Block *tangleold.Block
9697
}
9798

98-
// ManaVectorUpdateEvent is a container that acts as a dictionary for the EpochCommittable event related parameters.
99-
type ManaVectorUpdateEvent struct {
100-
// EI is the index of committable epoch.
101-
EI epoch.Index
102-
}
103-
10499
// SyncRangeEvent is a container that acts as a dictionary for the SyncRange event related parameters.
105100
type SyncRangeEvent struct {
106101
StartEI epoch.Index

packages/core/notarization/manager.go

+50-31
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import (
1010

1111
"github.com/iotaledger/hive.go/core/generics/event"
1212
"github.com/iotaledger/hive.go/core/generics/lo"
13+
"github.com/iotaledger/hive.go/core/generics/shrinkingmap"
1314
"github.com/iotaledger/hive.go/core/logger"
1415

1516
"github.com/iotaledger/goshimmer/packages/core/conflictdag"
17+
"github.com/iotaledger/goshimmer/packages/core/mana"
1618
"github.com/iotaledger/goshimmer/packages/node/clock"
1719

1820
"github.com/iotaledger/goshimmer/packages/core/epoch"
@@ -35,7 +37,7 @@ type Manager struct {
3537
epochCommitmentFactoryMutex sync.RWMutex
3638
bootstrapMutex sync.RWMutex
3739
options *ManagerOptions
38-
pendingConflictsCounters map[epoch.Index]uint64
40+
pendingConflictsCounters *shrinkingmap.ShrinkingMap[epoch.Index, uint64]
3941
log *logger.Logger
4042
Events *Events
4143
bootstrapped bool
@@ -55,7 +57,7 @@ func NewManager(epochCommitmentFactory *EpochCommitmentFactory, t *tangleold.Tan
5557
new = &Manager{
5658
tangle: t,
5759
epochCommitmentFactory: epochCommitmentFactory,
58-
pendingConflictsCounters: make(map[epoch.Index]uint64),
60+
pendingConflictsCounters: shrinkingmap.New[epoch.Index, uint64](),
5961
log: options.Log,
6062
options: options,
6163
Events: &Events{
@@ -66,7 +68,7 @@ func NewManager(epochCommitmentFactory *EpochCommitmentFactory, t *tangleold.Tan
6668
UTXOTreeInserted: event.New[*UTXOUpdatedEvent](),
6769
UTXOTreeRemoved: event.New[*UTXOUpdatedEvent](),
6870
EpochCommittable: event.New[*EpochCommittableEvent](),
69-
ManaVectorUpdate: event.New[*ManaVectorUpdateEvent](),
71+
ManaVectorUpdate: event.New[*mana.ManaVectorUpdateEvent](),
7072
Bootstrapped: event.New[*BootstrappedEvent](),
7173
SyncRange: event.New[*SyncRangeEvent](),
7274
ActivityTreeInserted: event.New[*ActivityTreeUpdatedEvent](),
@@ -172,7 +174,7 @@ func (m *Manager) LoadOutputsWithMetadata(outputsWithMetadatas []*ledger.OutputW
172174
}
173175
}
174176

175-
// LoadEpochDiffs updates the state tree from a given snapshot.
177+
// LoadEpochDiff loads an epoch diff.
176178
func (m *Manager) LoadEpochDiff(epochDiff *ledger.EpochDiff) {
177179
m.epochCommitmentFactoryMutex.Lock()
178180
defer m.epochCommitmentFactoryMutex.Unlock()
@@ -328,8 +330,6 @@ func (m *Manager) OnBlockStored(block *tangleold.Block) {
328330
latestCommittableEI := lo.PanicOnErr(m.epochCommitmentFactory.storage.latestCommittableEpochIndex())
329331
epochDeltaSeconds := time.Duration(int64(blockEI-latestCommittableEI)*epoch.Duration) * time.Second
330332

331-
m.log.Debugf("block committing to epoch %d stored, latest committable epoch is %d", blockEI, latestCommittableEI)
332-
333333
// If we are too far behind, we will warpsync
334334
if epochDeltaSeconds > m.options.BootstrapWindow {
335335
m.Events.SyncRange.Trigger(&SyncRangeEvent{
@@ -451,7 +451,7 @@ func (m *Manager) OnConflictAccepted(conflictID utxo.TransactionID) {
451451
}
452452

453453
// OnConflictConfirmed is the handler for conflict confirmed event.
454-
func (m *Manager) onConflictAccepted(conflictID utxo.TransactionID) ([]*EpochCommittableEvent, []*ManaVectorUpdateEvent) {
454+
func (m *Manager) onConflictAccepted(conflictID utxo.TransactionID) ([]*EpochCommittableEvent, []*mana.ManaVectorUpdateEvent) {
455455
m.epochCommitmentFactoryMutex.Lock()
456456
defer m.epochCommitmentFactoryMutex.Unlock()
457457

@@ -485,7 +485,7 @@ func (m *Manager) OnConflictRejected(conflictID utxo.TransactionID) {
485485
}
486486

487487
// OnConflictRejected is the handler for conflict created event.
488-
func (m *Manager) onConflictRejected(conflictID utxo.TransactionID) ([]*EpochCommittableEvent, []*ManaVectorUpdateEvent) {
488+
func (m *Manager) onConflictRejected(conflictID utxo.TransactionID) ([]*EpochCommittableEvent, []*mana.ManaVectorUpdateEvent) {
489489
m.epochCommitmentFactoryMutex.Lock()
490490
defer m.epochCommitmentFactoryMutex.Unlock()
491491

@@ -505,7 +505,7 @@ func (m *Manager) OnAcceptanceTimeUpdated(newTime time.Time) {
505505
}
506506

507507
// OnAcceptanceTimeUpdated is the handler for time updated event and returns events to be triggered.
508-
func (m *Manager) onAcceptanceTimeUpdated(newTime time.Time) ([]*EpochCommittableEvent, []*ManaVectorUpdateEvent) {
508+
func (m *Manager) onAcceptanceTimeUpdated(newTime time.Time) ([]*EpochCommittableEvent, []*mana.ManaVectorUpdateEvent) {
509509
m.epochCommitmentFactoryMutex.Lock()
510510
defer m.epochCommitmentFactoryMutex.Unlock()
511511

@@ -532,21 +532,14 @@ func (m *Manager) PendingConflictsCountAll() (pendingConflicts map[epoch.Index]u
532532
m.epochCommitmentFactoryMutex.RLock()
533533
defer m.epochCommitmentFactoryMutex.RUnlock()
534534

535-
pendingConflicts = make(map[epoch.Index]uint64, len(m.pendingConflictsCounters))
536-
for k, v := range m.pendingConflictsCounters {
535+
pendingConflicts = make(map[epoch.Index]uint64, m.pendingConflictsCounters.Size())
536+
m.pendingConflictsCounters.ForEach(func(k epoch.Index, v uint64) bool {
537537
pendingConflicts[k] = v
538-
}
538+
return true
539+
})
539540
return pendingConflicts
540541
}
541542

542-
// GetEpochDiff returns the epoch diff of an epoch.
543-
func (m *Manager) GetEpochDiff(ei epoch.Index) (spent []*ledger.OutputWithMetadata, created []*ledger.OutputWithMetadata) {
544-
m.epochCommitmentFactoryMutex.Lock()
545-
defer m.epochCommitmentFactoryMutex.Unlock()
546-
spent, created = m.epochCommitmentFactory.loadDiffUTXOs(ei)
547-
return
548-
}
549-
550543
// Bootstrapped returns the current value of pendingConflictsCount per epoch.
551544
func (m *Manager) Bootstrapped() bool {
552545
m.bootstrapMutex.RLock()
@@ -563,16 +556,20 @@ func (m *Manager) Shutdown() {
563556
m.epochCommitmentFactory.storage.shutdown()
564557
}
565558

566-
func (m *Manager) decreasePendingConflictCounter(ei epoch.Index) ([]*EpochCommittableEvent, []*ManaVectorUpdateEvent) {
567-
m.pendingConflictsCounters[ei]--
568-
if m.pendingConflictsCounters[ei] == 0 {
559+
func (m *Manager) decreasePendingConflictCounter(ei epoch.Index) ([]*EpochCommittableEvent, []*mana.ManaVectorUpdateEvent) {
560+
count, _ := m.pendingConflictsCounters.Get(ei)
561+
count--
562+
m.pendingConflictsCounters.Set(ei, count)
563+
if count == 0 {
569564
return m.moveLatestCommittableEpoch(ei)
570565
}
571566
return nil, nil
572567
}
573568

574569
func (m *Manager) increasePendingConflictCounter(ei epoch.Index) {
575-
m.pendingConflictsCounters[ei]++
570+
count, _ := m.pendingConflictsCounters.Get(ei)
571+
count++
572+
m.pendingConflictsCounters.Set(ei, count)
576573
}
577574

578575
func (m *Manager) includeTransactionInEpoch(txID utxo.TransactionID, ei epoch.Index, spent, created []*ledger.OutputWithMetadata) (err error) {
@@ -611,7 +608,7 @@ func (m *Manager) allPastConflictsAreResolved(ei epoch.Index) (conflictsResolved
611608
}
612609
// epoch is not committable if there are any not resolved conflicts in this and past epochs
613610
for index := lastEI; index <= ei; index++ {
614-
if m.pendingConflictsCounters[index] != 0 {
611+
if count, _ := m.pendingConflictsCounters.Get(index); count != 0 {
615612
return false
616613
}
617614
}
@@ -675,21 +672,31 @@ func (m *Manager) resolveOutputs(tx utxo.Transaction) (spentOutputsWithMetadata,
675672
return
676673
}
677674

678-
func (m *Manager) manaVectorUpdate(ei epoch.Index) (event *ManaVectorUpdateEvent) {
679-
return &ManaVectorUpdateEvent{
680-
EI: ei,
675+
func (m *Manager) manaVectorUpdate(ei epoch.Index) (event *mana.ManaVectorUpdateEvent) {
676+
manaEpoch := ei - epoch.Index(m.options.ManaEpochDelay)
677+
spent := []*ledger.OutputWithMetadata{}
678+
created := []*ledger.OutputWithMetadata{}
679+
680+
if manaEpoch > 0 {
681+
spent, created = m.epochCommitmentFactory.loadDiffUTXOs(manaEpoch)
682+
}
683+
684+
return &mana.ManaVectorUpdateEvent{
685+
EI: ei,
686+
Spent: spent,
687+
Created: created,
681688
}
682689
}
683690

684-
func (m *Manager) moveLatestCommittableEpoch(currentEpoch epoch.Index) ([]*EpochCommittableEvent, []*ManaVectorUpdateEvent) {
691+
func (m *Manager) moveLatestCommittableEpoch(currentEpoch epoch.Index) ([]*EpochCommittableEvent, []*mana.ManaVectorUpdateEvent) {
685692
latestCommittable, err := m.epochCommitmentFactory.storage.latestCommittableEpochIndex()
686693
if err != nil {
687694
m.log.Errorf("could not obtain last committed epoch index: %v", err)
688695
return nil, nil
689696
}
690697

691698
epochCommittableEvents := make([]*EpochCommittableEvent, 0)
692-
manaVectorUpdateEvents := make([]*ManaVectorUpdateEvent, 0)
699+
manaVectorUpdateEvents := make([]*mana.ManaVectorUpdateEvent, 0)
693700
for ei := latestCommittable + 1; ei <= currentEpoch; ei++ {
694701
if !m.isCommittable(ei) {
695702
break
@@ -715,11 +722,14 @@ func (m *Manager) moveLatestCommittableEpoch(currentEpoch epoch.Index) ([]*Epoch
715722
if manaVectorUpdateEvent := m.manaVectorUpdate(ei); manaVectorUpdateEvent != nil {
716723
manaVectorUpdateEvents = append(manaVectorUpdateEvents, manaVectorUpdateEvent)
717724
}
725+
726+
// We do not need to track pending conflicts for a committed epoch anymore.
727+
m.pendingConflictsCounters.Delete(ei)
718728
}
719729
return epochCommittableEvents, manaVectorUpdateEvents
720730
}
721731

722-
func (m *Manager) triggerEpochEvents(epochCommittableEvents []*EpochCommittableEvent, manaVectorUpdateEvents []*ManaVectorUpdateEvent) {
732+
func (m *Manager) triggerEpochEvents(epochCommittableEvents []*EpochCommittableEvent, manaVectorUpdateEvents []*mana.ManaVectorUpdateEvent) {
723733
for _, epochCommittableEvent := range epochCommittableEvents {
724734
m.Events.EpochCommittable.Trigger(epochCommittableEvent)
725735
}
@@ -755,6 +765,15 @@ type ManagerOptions struct {
755765
MinCommittableEpochAge time.Duration
756766
BootstrapWindow time.Duration
757767
Log *logger.Logger
768+
ManaEpochDelay uint
769+
}
770+
771+
// ManaEpochDelay specifies how many epochs the consensus mana booking is delayed with respect to the latest committable
772+
// epoch.
773+
func ManaEpochDelay(manaEpochDelay uint) ManagerOption {
774+
return func(options *ManagerOptions) {
775+
options.ManaEpochDelay = manaEpochDelay
776+
}
758777
}
759778

760779
// MinCommittableEpochAge specifies how old an epoch has to be for it to be committable.

0 commit comments

Comments
 (0)