From 89ad1cc4142fdd9c869b66657813d944d37a4df7 Mon Sep 17 00:00:00 2001 From: Hans Moog <3293976+hmoog@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:26:53 +0200 Subject: [PATCH 01/46] Feat: Persist mutations --- pkg/storage/prunable/prunable_slot.go | 5 +++++ pkg/storage/storage_prunable.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/pkg/storage/prunable/prunable_slot.go b/pkg/storage/prunable/prunable_slot.go index 337c7f1b4..7bb81f476 100644 --- a/pkg/storage/prunable/prunable_slot.go +++ b/pkg/storage/prunable/prunable_slot.go @@ -14,6 +14,7 @@ import ( const ( slotPrefixBlocks byte = iota slotPrefixRootBlocks + slotPrefixMutations slotPrefixAttestations slotPrefixAccountDiffs slotPrefixPerformanceFactors @@ -50,6 +51,10 @@ func (p *Prunable) RootBlocks(slot iotago.SlotIndex) (*slotstore.Store[iotago.Bl ), nil } +func (p *Prunable) Mutations(slot iotago.SlotIndex) (kvstore.KVStore, error) { + return p.getKVStoreFromSlot(slot, kvstore.Realm{slotPrefixMutations}) +} + func (p *Prunable) Attestations(slot iotago.SlotIndex) (kvstore.KVStore, error) { return p.getKVStoreFromSlot(slot, kvstore.Realm{slotPrefixAttestations}) } diff --git a/pkg/storage/storage_prunable.go b/pkg/storage/storage_prunable.go index cc1508f69..a65cd9406 100644 --- a/pkg/storage/storage_prunable.go +++ b/pkg/storage/storage_prunable.go @@ -37,6 +37,10 @@ func (s *Storage) RootBlocks(slot iotago.SlotIndex) (*slotstore.Store[iotago.Blo return s.prunable.RootBlocks(slot) } +func (s *Storage) Mutations(slot iotago.SlotIndex) (kvstore.KVStore, error) { + return s.prunable.Mutations(slot) +} + func (s *Storage) Attestations(slot iotago.SlotIndex) (kvstore.KVStore, error) { return s.prunable.Attestations(slot) } From 849aa717aba19c345f5bb924bf25f71a54b6eb05 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:06:11 +0200 Subject: [PATCH 02/46] Use mutations prunable storage to store mutations in mempool --- components/debugapi/transactions.go | 5 +- pkg/protocol/engine/ledger/ledger/ledger.go | 7 ++- pkg/protocol/engine/mempool/mempool.go | 2 +- .../engine/mempool/tests/testframework.go | 8 ++- pkg/protocol/engine/mempool/v1/mempool.go | 53 +++++++++++++------ .../engine/mempool/v1/mempool_test.go | 20 +++++-- pkg/protocol/engine/mempool/v1/state_diff.go | 6 +-- 7 files changed, 73 insertions(+), 28 deletions(-) diff --git a/components/debugapi/transactions.go b/components/debugapi/transactions.go index 1371882b9..b5b927f1f 100644 --- a/components/debugapi/transactions.go +++ b/components/debugapi/transactions.go @@ -17,7 +17,10 @@ func init() { func storeTransactionsPerSlot(scd *notarization.SlotCommittedDetails) error { slot := scd.Commitment.Slot() - stateDiff := deps.Protocol.MainEngineInstance().Ledger.MemPool().StateDiff(slot) + stateDiff, err := deps.Protocol.MainEngineInstance().Ledger.MemPool().StateDiff(slot) + if err != nil { + return ierrors.Wrapf(err, "failed to retrieve state diff for slot %d", slot) + } mutationsTree := ads.NewSet(mapdb.NewMapDB(), iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes) tcs := &TransactionsChangesResponse{ Index: slot, diff --git a/pkg/protocol/engine/ledger/ledger/ledger.go b/pkg/protocol/engine/ledger/ledger/ledger.go index f9bf12815..759b28348 100644 --- a/pkg/protocol/engine/ledger/ledger/ledger.go +++ b/pkg/protocol/engine/ledger/ledger/ledger.go @@ -69,7 +69,7 @@ func NewProvider() module.Provider[*engine.Engine, ledger.Ledger] { l.setRetainTransactionFailureFunc(e.Retainer.RetainTransactionFailure) - l.memPool = mempoolv1.New(l.executeStardustVM, l.resolveState, e.Workers.CreateGroup("MemPool"), l.conflictDAG, e, l.errorHandler, mempoolv1.WithForkAllTransactions[ledger.BlockVoteRank](true)) + l.memPool = mempoolv1.New(l.executeStardustVM, l.resolveState, e.Storage.Mutations, e.Workers.CreateGroup("MemPool"), l.conflictDAG, e, l.errorHandler, mempoolv1.WithForkAllTransactions[ledger.BlockVoteRank](true)) e.EvictionState.Events.SlotEvicted.Hook(l.memPool.Evict) l.manaManager = mana.NewManager(l.apiProvider, l.resolveAccountOutput) @@ -148,7 +148,10 @@ func (l *Ledger) CommitSlot(slot iotago.SlotIndex) (stateRoot iotago.Identifier, panic(ierrors.Errorf("there is a gap in the ledgerstate %d vs %d", ledgerIndex+1, slot)) } - stateDiff := l.memPool.StateDiff(slot) + stateDiff, err := l.memPool.StateDiff(slot) + if err != nil { + return iotago.Identifier{}, iotago.Identifier{}, iotago.Identifier{}, ierrors.Errorf("failed to retrieve state diff for slot %d: %w", slot, err) + } // collect outputs and allotments from the "uncompacted" stateDiff // outputs need to be processed in the "uncompacted" version of the state diff, as we need to be able to store diff --git a/pkg/protocol/engine/mempool/mempool.go b/pkg/protocol/engine/mempool/mempool.go index 5ef3891fb..25fda1250 100644 --- a/pkg/protocol/engine/mempool/mempool.go +++ b/pkg/protocol/engine/mempool/mempool.go @@ -23,7 +23,7 @@ type MemPool[VoteRank conflictdag.VoteRankType[VoteRank]] interface { TransactionMetadataByAttachment(blockID iotago.BlockID) (transaction TransactionMetadata, exists bool) - StateDiff(slot iotago.SlotIndex) StateDiff + StateDiff(slot iotago.SlotIndex) (StateDiff, error) Evict(slot iotago.SlotIndex) } diff --git a/pkg/protocol/engine/mempool/tests/testframework.go b/pkg/protocol/engine/mempool/tests/testframework.go index 8e93ee924..aa4a45e6c 100644 --- a/pkg/protocol/engine/mempool/tests/testframework.go +++ b/pkg/protocol/engine/mempool/tests/testframework.go @@ -108,7 +108,10 @@ func (t *TestFramework) AttachTransaction(transactionAlias, blockAlias string, s } func (t *TestFramework) CommitSlot(slot iotago.SlotIndex) { - stateDiff := t.Instance.StateDiff(slot) + stateDiff, err := t.Instance.StateDiff(slot) + if err != nil { + panic(err) + } stateDiff.CreatedStates().ForEach(func(_ iotago.OutputID, state mempool.OutputStateMetadata) bool { t.ledgerState.AddOutputState(state.State()) @@ -323,7 +326,8 @@ func (t *TestFramework) requireMarkedBooked(transactionAliases ...string) { } func (t *TestFramework) AssertStateDiff(slot iotago.SlotIndex, spentOutputAliases, createdOutputAliases, transactionAliases []string) { - stateDiff := t.Instance.StateDiff(slot) + stateDiff, err := t.Instance.StateDiff(slot) + require.NoError(t.test, err) require.Equal(t.test, len(spentOutputAliases), stateDiff.DestroyedStates().Size()) require.Equal(t.test, len(createdOutputAliases), stateDiff.CreatedStates().Size()) diff --git a/pkg/protocol/engine/mempool/v1/mempool.go b/pkg/protocol/engine/mempool/v1/mempool.go index caef76ba1..5290bfb8e 100644 --- a/pkg/protocol/engine/mempool/v1/mempool.go +++ b/pkg/protocol/engine/mempool/v1/mempool.go @@ -7,6 +7,7 @@ import ( "github.com/iotaledger/hive.go/ds" "github.com/iotaledger/hive.go/ds/shrinkingmap" "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/hive.go/kvstore" "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/hive.go/runtime/options" @@ -29,6 +30,8 @@ type MemPool[VoteRank conflictdag.VoteRankType[VoteRank]] struct { // resolveState is the function that is used to request state from the ledger. resolveState mempool.StateReferenceResolver + mutationsFunc func(iotago.SlotIndex) (kvstore.KVStore, error) + // attachments is the storage that is used to keep track of the attachments of transactions. attachments *memstorage.IndexedStorage[iotago.SlotIndex, iotago.BlockID, *TransactionMetadata] @@ -61,11 +64,12 @@ type MemPool[VoteRank conflictdag.VoteRankType[VoteRank]] struct { } // New is the constructor of the MemPool. -func New[VoteRank conflictdag.VoteRankType[VoteRank]](vm mempool.VM, inputResolver mempool.StateReferenceResolver, workers *workerpool.Group, conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, iotago.OutputID, VoteRank], apiProvider iotago.APIProvider, errorHandler func(error), opts ...options.Option[MemPool[VoteRank]]) *MemPool[VoteRank] { +func New[VoteRank conflictdag.VoteRankType[VoteRank]](vm mempool.VM, inputResolver mempool.StateReferenceResolver, mutationsFunc func(iotago.SlotIndex) (kvstore.KVStore, error), workers *workerpool.Group, conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, iotago.OutputID, VoteRank], apiProvider iotago.APIProvider, errorHandler func(error), opts ...options.Option[MemPool[VoteRank]]) *MemPool[VoteRank] { return options.Apply(&MemPool[VoteRank]{ transactionAttached: event.New1[mempool.TransactionMetadata](), executeStateTransition: vm, resolveState: inputResolver, + mutationsFunc: mutationsFunc, attachments: memstorage.NewIndexedStorage[iotago.SlotIndex, iotago.BlockID, *TransactionMetadata](), cachedTransactions: shrinkingmap.New[iotago.TransactionID, *TransactionMetadata](), cachedStateRequests: shrinkingmap.New[iotago.Identifier, *promise.Promise[mempool.State]](), @@ -153,12 +157,17 @@ func (m *MemPool[VoteRank]) TransactionMetadataByAttachment(blockID iotago.Block } // StateDiff returns the state diff for the given slot. -func (m *MemPool[VoteRank]) StateDiff(slot iotago.SlotIndex) mempool.StateDiff { +func (m *MemPool[VoteRank]) StateDiff(slot iotago.SlotIndex) (mempool.StateDiff, error) { if stateDiff, exists := m.stateDiffs.Get(slot); exists { - return stateDiff + return stateDiff, nil + } + + kv, err := m.mutationsFunc(slot) + if err != nil { + return nil, ierrors.Wrapf(err, "failed to get state diff for slot %d", slot) } - return NewStateDiff(slot) + return NewStateDiff(slot, kv), nil } // Evict evicts the slot with the given slot from the MemPool. @@ -374,10 +383,13 @@ func (m *MemPool[VoteRank]) updateStateDiffs(transaction *TransactionMetadata, p } if transaction.IsAccepted() && newIndex != 0 { - if stateDiff, evicted := m.stateDiff(newIndex); !evicted { - if err := stateDiff.AddTransaction(transaction, m.errorHandler); err != nil { - return ierrors.Wrapf(err, "failed to add transaction to state diff, txID: %s", transaction.ID()) - } + stateDiff, err := m.stateDiff(newIndex) + if err != nil { + return ierrors.Wrapf(err, "failed to get state diff for slot %d", newIndex) + } + + if err = stateDiff.AddTransaction(transaction, m.errorHandler); err != nil { + return ierrors.Wrapf(err, "failed to add transaction to state diff, txID: %s", transaction.ID()) } } @@ -392,21 +404,30 @@ func (m *MemPool[VoteRank]) setup() { }) } -func (m *MemPool[VoteRank]) stateDiff(slot iotago.SlotIndex) (stateDiff *StateDiff, evicted bool) { +func (m *MemPool[VoteRank]) stateDiff(slot iotago.SlotIndex) (*StateDiff, error) { if m.lastEvictedSlot >= slot { - return nil, true + return nil, ierrors.Errorf("slot %d is older than last evicted slot %d", slot, m.lastEvictedSlot) } - return lo.Return1(m.stateDiffs.GetOrCreate(slot, func() *StateDiff { return NewStateDiff(slot) })), false + kv, err := m.mutationsFunc(slot) + if err != nil { + return nil, ierrors.Wrapf(err, "failed to get state diff for slot %d", slot) + } + + return lo.Return1(m.stateDiffs.GetOrCreate(slot, func() *StateDiff { return NewStateDiff(slot, kv) })), nil } func (m *MemPool[VoteRank]) setupTransaction(transaction *TransactionMetadata) { transaction.OnAccepted(func() { - if slot := transaction.EarliestIncludedAttachment().Slot(); slot > 0 { - if stateDiff, evicted := m.stateDiff(slot); !evicted { - if err := stateDiff.AddTransaction(transaction, m.errorHandler); err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to add transaction to state diff, txID: %s", transaction.ID())) - } + // Transactions can only become accepted if there is at least one attachment is included. + if slot := transaction.EarliestIncludedAttachment().Slot(); slot != 0 { + stateDiff, err := m.stateDiff(slot) + if err != nil { + m.errorHandler(ierrors.Wrapf(err, "failed to get state diff for slot %d", slot)) + } + + if err := stateDiff.AddTransaction(transaction, m.errorHandler); err != nil { + m.errorHandler(ierrors.Wrapf(err, "failed to add transaction to state diff, txID: %s", transaction.ID())) } } }) diff --git a/pkg/protocol/engine/mempool/v1/mempool_test.go b/pkg/protocol/engine/mempool/v1/mempool_test.go index f7f71b086..73f7311ed 100644 --- a/pkg/protocol/engine/mempool/v1/mempool_test.go +++ b/pkg/protocol/engine/mempool/v1/mempool_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/require" "github.com/iotaledger/hive.go/ds/shrinkingmap" + "github.com/iotaledger/hive.go/kvstore" + "github.com/iotaledger/hive.go/kvstore/mapdb" "github.com/iotaledger/hive.go/runtime/memanalyzer" "github.com/iotaledger/hive.go/runtime/workerpool" "github.com/iotaledger/iota-core/pkg/core/account" @@ -34,11 +36,15 @@ func TestMemPoolV1_InterfaceWithForkingEverything(t *testing.T) { func TestMempoolV1_ResourceCleanup(t *testing.T) { workers := workerpool.NewGroup(t.Name()) + mutationsFunc := func(index iotago.SlotIndex) (kvstore.KVStore, error) { + return mapdb.NewMapDB(), nil + } + ledgerState := ledgertests.New(ledgertests.NewMockedState(iotago.TransactionID{}, 0)) conflictDAG := conflictdagv1.New[iotago.TransactionID, iotago.OutputID, vote.MockedRank](func() int { return 0 }) mempoolInstance := New[vote.MockedRank](mempooltests.VM, func(reference iotago.Input) *promise.Promise[mempool.State] { return ledgerState.ResolveOutputState(reference.(*iotago.UTXOInput).OutputID()) - }, workers, conflictDAG, api.SingleVersionProvider(tpkg.TestAPI), func(error) {}) + }, mutationsFunc, workers, conflictDAG, api.SingleVersionProvider(tpkg.TestAPI), func(error) {}) tf := mempooltests.NewTestFramework(t, mempoolInstance, conflictDAG, ledgerState, workers) @@ -104,9 +110,13 @@ func newTestFramework(t *testing.T) *mempooltests.TestFramework { ledgerState := ledgertests.New(ledgertests.NewMockedState(iotago.TransactionID{}, 0)) conflictDAG := conflictdagv1.New[iotago.TransactionID, iotago.OutputID, vote.MockedRank](account.NewAccounts().SelectCommittee().SeatCount) + mutationsFunc := func(index iotago.SlotIndex) (kvstore.KVStore, error) { + return mapdb.NewMapDB(), nil + } + return mempooltests.NewTestFramework(t, New[vote.MockedRank](mempooltests.VM, func(reference iotago.Input) *promise.Promise[mempool.State] { return ledgerState.ResolveOutputState(reference.(*iotago.UTXOInput).OutputID()) - }, workers, conflictDAG, api.SingleVersionProvider(tpkg.TestAPI), func(error) {}), conflictDAG, ledgerState, workers) + }, mutationsFunc, workers, conflictDAG, api.SingleVersionProvider(tpkg.TestAPI), func(error) {}), conflictDAG, ledgerState, workers) } func newForkingTestFramework(t *testing.T) *mempooltests.TestFramework { @@ -115,7 +125,11 @@ func newForkingTestFramework(t *testing.T) *mempooltests.TestFramework { ledgerState := ledgertests.New(ledgertests.NewMockedState(iotago.TransactionID{}, 0)) conflictDAG := conflictdagv1.New[iotago.TransactionID, iotago.OutputID, vote.MockedRank](account.NewAccounts().SelectCommittee().SeatCount) + mutationsFunc := func(index iotago.SlotIndex) (kvstore.KVStore, error) { + return mapdb.NewMapDB(), nil + } + return mempooltests.NewTestFramework(t, New[vote.MockedRank](mempooltests.VM, func(reference iotago.Input) *promise.Promise[mempool.State] { return ledgerState.ResolveOutputState(reference.(*iotago.UTXOInput).OutputID()) - }, workers, conflictDAG, api.SingleVersionProvider(tpkg.TestAPI), func(error) {}, WithForkAllTransactions[vote.MockedRank](true)), conflictDAG, ledgerState, workers) + }, mutationsFunc, workers, conflictDAG, api.SingleVersionProvider(tpkg.TestAPI), func(error) {}, WithForkAllTransactions[vote.MockedRank](true)), conflictDAG, ledgerState, workers) } diff --git a/pkg/protocol/engine/mempool/v1/state_diff.go b/pkg/protocol/engine/mempool/v1/state_diff.go index ce7544e8e..9a93ea100 100644 --- a/pkg/protocol/engine/mempool/v1/state_diff.go +++ b/pkg/protocol/engine/mempool/v1/state_diff.go @@ -5,7 +5,7 @@ import ( "github.com/iotaledger/hive.go/ds/orderedmap" "github.com/iotaledger/hive.go/ds/shrinkingmap" "github.com/iotaledger/hive.go/ierrors" - "github.com/iotaledger/hive.go/kvstore/mapdb" + "github.com/iotaledger/hive.go/kvstore" "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool" iotago "github.com/iotaledger/iota.go/v4" ) @@ -24,14 +24,14 @@ type StateDiff struct { mutations ads.Set[iotago.TransactionID] } -func NewStateDiff(slot iotago.SlotIndex) *StateDiff { +func NewStateDiff(slot iotago.SlotIndex, kv kvstore.KVStore) *StateDiff { return &StateDiff{ slot: slot, spentOutputs: shrinkingmap.New[iotago.OutputID, mempool.OutputStateMetadata](), createdOutputs: shrinkingmap.New[iotago.OutputID, mempool.OutputStateMetadata](), executedTransactions: orderedmap.New[iotago.TransactionID, mempool.TransactionMetadata](), stateUsageCounters: shrinkingmap.New[iotago.OutputID, int](), - mutations: ads.NewSet(mapdb.NewMapDB(), iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes), + mutations: ads.NewSet(kv, iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes), } } From a77d2de13a9c0fd26dabe3678945125832eb8705 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:31:42 +0200 Subject: [PATCH 03/46] Update protobuf structure for warpsync response to include mutations proof and accepted transactionIDs --- .../protocols/core/models/message.pb.go | 64 +++++++++++++------ .../protocols/core/models/message.proto | 6 +- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/pkg/network/protocols/core/models/message.pb.go b/pkg/network/protocols/core/models/message.pb.go index 11cc34720..66dbe6a16 100644 --- a/pkg/network/protocols/core/models/message.pb.go +++ b/pkg/network/protocols/core/models/message.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.12.4 +// protoc-gen-go v1.30.0 +// protoc v4.23.4 // source: pkg/network/protocols/core/models/message.proto package models @@ -26,6 +26,7 @@ type Packet struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Body: + // // *Packet_Block // *Packet_BlockRequest // *Packet_SlotCommitment @@ -534,9 +535,11 @@ type WarpSyncResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CommitmentId []byte `protobuf:"bytes,1,opt,name=commitment_id,json=commitmentId,proto3" json:"commitment_id,omitempty"` - BlockIds []byte `protobuf:"bytes,2,opt,name=block_ids,json=blockIds,proto3" json:"block_ids,omitempty"` - MerkleProof []byte `protobuf:"bytes,3,opt,name=merkle_proof,json=merkleProof,proto3" json:"merkle_proof,omitempty"` + CommitmentId []byte `protobuf:"bytes,1,opt,name=commitment_id,json=commitmentId,proto3" json:"commitment_id,omitempty"` + BlockIds []byte `protobuf:"bytes,2,opt,name=block_ids,json=blockIds,proto3" json:"block_ids,omitempty"` + TangleMerkleProof []byte `protobuf:"bytes,3,opt,name=tangle_merkle_proof,json=tangleMerkleProof,proto3" json:"tangle_merkle_proof,omitempty"` + TransactionIds []byte `protobuf:"bytes,4,opt,name=transaction_ids,json=transactionIds,proto3" json:"transaction_ids,omitempty"` + MutationsMerkleProof []byte `protobuf:"bytes,5,opt,name=mutations_merkle_proof,json=mutationsMerkleProof,proto3" json:"mutations_merkle_proof,omitempty"` } func (x *WarpSyncResponse) Reset() { @@ -585,9 +588,23 @@ func (x *WarpSyncResponse) GetBlockIds() []byte { return nil } -func (x *WarpSyncResponse) GetMerkleProof() []byte { +func (x *WarpSyncResponse) GetTangleMerkleProof() []byte { if x != nil { - return x.MerkleProof + return x.TangleMerkleProof + } + return nil +} + +func (x *WarpSyncResponse) GetTransactionIds() []byte { + if x != nil { + return x.TransactionIds + } + return nil +} + +func (x *WarpSyncResponse) GetMutationsMerkleProof() []byte { + if x != nil { + return x.MutationsMerkleProof } return nil } @@ -659,19 +676,26 @@ var file_pkg_network_protocols_core_models_message_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x57, 0x61, 0x72, 0x70, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x10, 0x57, 0x61, 0x72, 0x70, 0x53, 0x79, - 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x73, 0x12, 0x21, 0x0a, 0x0c, - 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, - 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6f, - 0x74, 0x61, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2f, 0x69, 0x6f, 0x74, 0x61, 0x2d, 0x63, 0x6f, - 0x72, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xe3, 0x01, 0x0a, 0x10, 0x57, 0x61, 0x72, 0x70, 0x53, + 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x73, 0x12, 0x2e, 0x0a, + 0x13, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x70, + 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x74, 0x61, 0x6e, 0x67, + 0x6c, 0x65, 0x4d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x27, 0x0a, + 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x5f, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x4d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x43, 0x5a, 0x41, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6f, 0x74, 0x61, 0x6c, + 0x65, 0x64, 0x67, 0x65, 0x72, 0x2f, 0x69, 0x6f, 0x74, 0x61, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, + 0x70, 0x6b, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/network/protocols/core/models/message.proto b/pkg/network/protocols/core/models/message.proto index 6ca73a616..11cfa0860 100644 --- a/pkg/network/protocols/core/models/message.proto +++ b/pkg/network/protocols/core/models/message.proto @@ -50,5 +50,7 @@ message WarpSyncRequest { message WarpSyncResponse { bytes commitment_id = 1; bytes block_ids = 2; - bytes merkle_proof = 3; -} \ No newline at end of file + bytes tangle_merkle_proof = 3; + bytes transaction_ids = 4; + bytes mutations_merkle_proof = 5; +} From 970e0fb696a9e46b9577a9bf58ffa0992c421c11 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:35:19 +0200 Subject: [PATCH 04/46] Implement warpsync response to include mutations proof and accepted transactionIDs and hand it over to warp sync --- pkg/network/protocols/core/events.go | 4 +-- pkg/network/protocols/core/protocol.go | 2 +- pkg/network/protocols/core/warp_sync.go | 30 +++++++++++++++++------ pkg/protocol/block_dispatcher.go | 13 +++++++--- pkg/protocol/engine/committed_slot_api.go | 24 ++++++++++++++++++ 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/pkg/network/protocols/core/events.go b/pkg/network/protocols/core/events.go index 47eb4e771..8577388f6 100644 --- a/pkg/network/protocols/core/events.go +++ b/pkg/network/protocols/core/events.go @@ -17,7 +17,7 @@ type Events struct { AttestationsReceived *event.Event4[*model.Commitment, []*iotago.Attestation, *merklehasher.Proof[iotago.Identifier], peer.ID] AttestationsRequestReceived *event.Event2[iotago.CommitmentID, peer.ID] WarpSyncRequestReceived *event.Event2[iotago.CommitmentID, peer.ID] - WarpSyncResponseReceived *event.Event4[iotago.CommitmentID, iotago.BlockIDs, *merklehasher.Proof[iotago.Identifier], peer.ID] + WarpSyncResponseReceived *event.Event6[iotago.CommitmentID, iotago.BlockIDs, *merklehasher.Proof[iotago.Identifier], iotago.TransactionIDs, *merklehasher.Proof[iotago.Identifier], peer.ID] Error *event.Event2[error, peer.ID] event.Group[Events, *Events] @@ -33,7 +33,7 @@ var NewEvents = event.CreateGroupConstructor(func() (newEvents *Events) { AttestationsReceived: event.New4[*model.Commitment, []*iotago.Attestation, *merklehasher.Proof[iotago.Identifier], peer.ID](), AttestationsRequestReceived: event.New2[iotago.CommitmentID, peer.ID](), WarpSyncRequestReceived: event.New2[iotago.CommitmentID, peer.ID](), - WarpSyncResponseReceived: event.New4[iotago.CommitmentID, iotago.BlockIDs, *merklehasher.Proof[iotago.Identifier], peer.ID](), + WarpSyncResponseReceived: event.New6[iotago.CommitmentID, iotago.BlockIDs, *merklehasher.Proof[iotago.Identifier], iotago.TransactionIDs, *merklehasher.Proof[iotago.Identifier], peer.ID](), Error: event.New2[error, peer.ID](), } }) diff --git a/pkg/network/protocols/core/protocol.go b/pkg/network/protocols/core/protocol.go index 5652c001f..c10160474 100644 --- a/pkg/network/protocols/core/protocol.go +++ b/pkg/network/protocols/core/protocol.go @@ -127,7 +127,7 @@ func (p *Protocol) handlePacket(nbr peer.ID, packet proto.Message) (err error) { case *nwmodels.Packet_WarpSyncRequest: p.handleWarpSyncRequest(packetBody.WarpSyncRequest.GetCommitmentId(), nbr) case *nwmodels.Packet_WarpSyncResponse: - p.handleWarpSyncResponse(packetBody.WarpSyncResponse.GetCommitmentId(), packetBody.WarpSyncResponse.GetBlockIds(), packetBody.WarpSyncResponse.GetMerkleProof(), nbr) + p.handleWarpSyncResponse(packetBody.WarpSyncResponse.GetCommitmentId(), packetBody.WarpSyncResponse.GetBlockIds(), packetBody.WarpSyncResponse.GetTangleMerkleProof(), packetBody.WarpSyncResponse.GetTransactionIds(), packetBody.WarpSyncResponse.GetMutationsMerkleProof(), nbr) default: return ierrors.Errorf("unsupported packet; packet=%+v, packetBody=%T-%+v", packet, packetBody, packetBody) } diff --git a/pkg/network/protocols/core/warp_sync.go b/pkg/network/protocols/core/warp_sync.go index 95f66798f..c6dd7a02f 100644 --- a/pkg/network/protocols/core/warp_sync.go +++ b/pkg/network/protocols/core/warp_sync.go @@ -19,14 +19,16 @@ func (p *Protocol) SendWarpSyncRequest(id iotago.CommitmentID, to ...peer.ID) { }}, to...) } -func (p *Protocol) SendWarpSyncResponse(id iotago.CommitmentID, blockIDs iotago.BlockIDs, merkleProof *merklehasher.Proof[iotago.Identifier], to ...peer.ID) { +func (p *Protocol) SendWarpSyncResponse(id iotago.CommitmentID, blockIDs iotago.BlockIDs, tangleMerkleProof *merklehasher.Proof[iotago.Identifier], transactionIDs iotago.TransactionIDs, mutationsMerkleProof *merklehasher.Proof[iotago.Identifier], to ...peer.ID) { serializer := p.apiProvider.APIForSlot(id.Slot()) p.network.Send(&nwmodels.Packet{Body: &nwmodels.Packet_WarpSyncResponse{ WarpSyncResponse: &nwmodels.WarpSyncResponse{ - CommitmentId: lo.PanicOnErr(id.Bytes()), - BlockIds: lo.PanicOnErr(serializer.Encode(blockIDs)), - MerkleProof: lo.PanicOnErr(merkleProof.Bytes()), + CommitmentId: lo.PanicOnErr(id.Bytes()), + BlockIds: lo.PanicOnErr(serializer.Encode(blockIDs)), + TangleMerkleProof: lo.PanicOnErr(tangleMerkleProof.Bytes()), + TransactionIds: lo.PanicOnErr(serializer.Encode(transactionIDs)), + MutationsMerkleProof: lo.PanicOnErr(mutationsMerkleProof.Bytes()), }, }}, to...) } @@ -44,7 +46,7 @@ func (p *Protocol) handleWarpSyncRequest(commitmentIDBytes []byte, id peer.ID) { }) } -func (p *Protocol) handleWarpSyncResponse(commitmentIDBytes []byte, blockIDsBytes []byte, merkleProofBytes []byte, id peer.ID) { +func (p *Protocol) handleWarpSyncResponse(commitmentIDBytes []byte, blockIDsBytes []byte, tangleMerkleProofBytes []byte, transactionIDsBytes []byte, mutationProofBytes []byte, id peer.ID) { p.workerPool.Submit(func() { commitmentID, _, err := iotago.SlotIdentifierFromBytes(commitmentIDBytes) if err != nil { @@ -60,13 +62,27 @@ func (p *Protocol) handleWarpSyncResponse(commitmentIDBytes []byte, blockIDsByte return } - merkleProof, _, err := merklehasher.ProofFromBytes[iotago.Identifier](merkleProofBytes) + tangleMerkleProof, _, err := merklehasher.ProofFromBytes[iotago.Identifier](tangleMerkleProofBytes) + if err != nil { + p.Events.Error.Trigger(ierrors.Wrapf(err, "failed to deserialize merkle proof when receiving waprsync response for commitment %s", commitmentID), id) + + return + } + + var transactionIDs iotago.TransactionIDs + if _, err = p.apiProvider.APIForSlot(commitmentID.Slot()).Decode(transactionIDsBytes, &transactionIDs, serix.WithValidation()); err != nil { + p.Events.Error.Trigger(ierrors.Wrap(err, "failed to deserialize transaction ids"), id) + + return + } + + mutationProof, _, err := merklehasher.ProofFromBytes[iotago.Identifier](mutationProofBytes) if err != nil { p.Events.Error.Trigger(ierrors.Wrapf(err, "failed to deserialize merkle proof when receiving waprsync response for commitment %s", commitmentID), id) return } - p.Events.WarpSyncResponseReceived.Trigger(commitmentID, blockIDs, merkleProof, id) + p.Events.WarpSyncResponseReceived.Trigger(commitmentID, blockIDs, tangleMerkleProof, transactionIDs, mutationProof, id) }) } diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index a1c1bfac8..b740c99de 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -151,9 +151,9 @@ func (b *BlockDispatcher) initNetworkConnection() { }, b.warpSyncWorkers) }) - b.protocol.Events.Network.WarpSyncResponseReceived.Hook(func(commitmentID iotago.CommitmentID, blockIDs iotago.BlockIDs, merkleProof *merklehasher.Proof[iotago.Identifier], src peer.ID) { + b.protocol.Events.Network.WarpSyncResponseReceived.Hook(func(commitmentID iotago.CommitmentID, blockIDs iotago.BlockIDs, tangleMerkleProof *merklehasher.Proof[iotago.Identifier], transactionIDs iotago.TransactionIDs, mutationMerkleProof *merklehasher.Proof[iotago.Identifier], src peer.ID) { b.runTask(func() { - b.protocol.HandleError(b.processWarpSyncResponse(commitmentID, blockIDs, merkleProof, src)) + b.protocol.HandleError(b.processWarpSyncResponse(commitmentID, blockIDs, tangleMerkleProof, transactionIDs, mutationMerkleProof, src)) }, b.warpSyncWorkers) }) } @@ -179,18 +179,23 @@ func (b *BlockDispatcher) processWarpSyncRequest(commitmentID iotago.CommitmentI return ierrors.Wrapf(err, "failed to get block IDs from slot %d", commitmentID.Slot()) } + transactionIDs, err := committedSlot.TransactionIDs() + if err != nil { + return ierrors.Wrapf(err, "failed to get transaction IDs from slot %d", commitmentID.Slot()) + } + roots, err := committedSlot.Roots() if err != nil { return ierrors.Wrapf(err, "failed to get roots from slot %d", commitmentID.Slot()) } - b.protocol.networkProtocol.SendWarpSyncResponse(commitmentID, blockIDs, roots.TangleProof(), src) + b.protocol.networkProtocol.SendWarpSyncResponse(commitmentID, blockIDs, roots.TangleProof(), transactionIDs, roots.MutationProof(), src) return nil } // processWarpSyncResponse processes a WarpSync response. -func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.CommitmentID, blockIDs iotago.BlockIDs, merkleProof *merklehasher.Proof[iotago.Identifier], _ peer.ID) error { +func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.CommitmentID, blockIDs iotago.BlockIDs, merkleProof *merklehasher.Proof[iotago.Identifier], transactionIDs iotago.TransactionIDs, mutationMerkleProof *merklehasher.Proof[iotago.Identifier], _ peer.ID) error { if b.processedWarpSyncRequests.Has(commitmentID) { return nil } diff --git a/pkg/protocol/engine/committed_slot_api.go b/pkg/protocol/engine/committed_slot_api.go index 35ee99199..579f27a55 100644 --- a/pkg/protocol/engine/committed_slot_api.go +++ b/pkg/protocol/engine/committed_slot_api.go @@ -1,6 +1,7 @@ package engine import ( + "github.com/iotaledger/hive.go/ads" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota-core/pkg/model" iotago "github.com/iotaledger/iota.go/v4" @@ -71,3 +72,26 @@ func (c *CommittedSlotAPI) BlockIDs() (blockIDs iotago.BlockIDs, err error) { return blockIDs, nil } + +func (c *CommittedSlotAPI) TransactionIDs() (iotago.TransactionIDs, error) { + if c.engine.Storage.Settings().LatestCommitment().Slot() < c.CommitmentID.Slot() { + return nil, ierrors.Errorf("slot %d is not committed yet", c.CommitmentID) + } + + store, err := c.engine.Storage.Mutations(c.CommitmentID.Slot()) + if err != nil { + return nil, ierrors.Errorf("failed to get mutations of slot index %d", c.CommitmentID.Slot()) + } + + set := ads.NewSet(store, iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes) + transactionIDs := make(iotago.TransactionIDs, 0, set.Size()) + + if err = set.Stream(func(key iotago.TransactionID) error { + transactionIDs = append(transactionIDs, key) + return nil + }); err != nil { + return nil, ierrors.Wrapf(err, "failed to iterate over mutations of slot %d", c.CommitmentID.Slot()) + } + + return transactionIDs, nil +} From 0ec130504c99b879f251743f5781ed88f04ad85c Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:54:49 +0200 Subject: [PATCH 05/46] Extend warp sync to validate mutation proof and force accept blocks, transactions and force commit the synced slot --- pkg/protocol/block_dispatcher.go | 75 ++++++++++++++-- pkg/protocol/engine/blocks/block.go | 40 ++++++--- .../engine/consensus/blockgadget/gadget.go | 1 + .../acceptance_ratification.go | 9 ++ .../engine/mempool/conflictdag/conflictdag.go | 1 + .../conflictdag/conflictdagv1/conflictdag.go | 9 ++ .../engine/notarization/notarization.go | 4 + .../notarization/slotnotarization/manager.go | 89 ++++++++++--------- 8 files changed, 167 insertions(+), 61 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index b740c99de..5fa9f1b88 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -1,6 +1,7 @@ package protocol import ( + "sync/atomic" "time" "github.com/libp2p/go-libp2p/core/peer" @@ -195,11 +196,12 @@ func (b *BlockDispatcher) processWarpSyncRequest(commitmentID iotago.CommitmentI } // processWarpSyncResponse processes a WarpSync response. -func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.CommitmentID, blockIDs iotago.BlockIDs, merkleProof *merklehasher.Proof[iotago.Identifier], transactionIDs iotago.TransactionIDs, mutationMerkleProof *merklehasher.Proof[iotago.Identifier], _ peer.ID) error { +func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.CommitmentID, blockIDs iotago.BlockIDs, tangleMerkleProof *merklehasher.Proof[iotago.Identifier], transactionIDs iotago.TransactionIDs, mutationMerkleProof *merklehasher.Proof[iotago.Identifier], _ peer.ID) error { if b.processedWarpSyncRequests.Has(commitmentID) { return nil } + // First we make sure that the commitment, the provided blockIDs with tangle proof and the provided transactionIDs with mutation proof are valid. chainCommitment, exists := b.protocol.ChainManager.Commitment(commitmentID) if !exists { return ierrors.Errorf("failed to get chain commitment for %s", commitmentID) @@ -212,19 +214,82 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment acceptedBlocks := ads.NewSet[iotago.BlockID](mapdb.NewMapDB(), iotago.BlockID.Bytes, iotago.SlotIdentifierFromBytes) for _, blockID := range blockIDs { - _ = acceptedBlocks.Add(blockID) // a mapdb can newer return an error + _ = acceptedBlocks.Add(blockID) // a mapdb can never return an error } - if !iotago.VerifyProof(merkleProof, iotago.Identifier(acceptedBlocks.Root()), chainCommitment.Commitment().RootsID()) { - return ierrors.Errorf("failed to verify merkle proof for %s", commitmentID) + if !iotago.VerifyProof(tangleMerkleProof, iotago.Identifier(acceptedBlocks.Root()), chainCommitment.Commitment().RootsID()) { + return ierrors.Errorf("failed to verify tangle merkle proof for %s", commitmentID) + } + + acceptedTransactionIDs := ads.NewSet[iotago.BlockID](mapdb.NewMapDB(), iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes) + for _, transactionID := range transactionIDs { + _ = acceptedTransactionIDs.Add(transactionID) // a mapdb can never return an error + } + + if !iotago.VerifyProof(mutationMerkleProof, iotago.Identifier(acceptedTransactionIDs.Root()), chainCommitment.Commitment().RootsID()) { + return ierrors.Errorf("failed to verify mutation merkle proof for %s", commitmentID) } b.pendingWarpSyncRequests.StopTicker(commitmentID) b.processedWarpSyncRequests.Add(commitmentID) + // Once all blocks are booked we + // 1. Mark all transactions as accepted + // 2. Mark all blocks as accepted + // 3. Force commitment of the slot + var bookedBlocks atomic.Uint32 + bookedBlocks.Store(uint32(len(blockIDs))) + + var notarizedBlocks atomic.Uint32 + notarizedBlocks.Store(uint32(len(blockIDs))) + + blockBookedCallback := func(_, _ bool) { + if bookedBlocks.Add(-1) != 0 { + return + } + + // 1. Mark all transactions as accepted + for _, transactionID := range transactionIDs { + targetEngine.Ledger.ConflictDAG().SetAccepted(transactionID) + } + + // 2. Mark all blocks as accepted + for _, blockID := range blockIDs { + block, exists := targetEngine.BlockCache.Block(blockID) + if !exists { // this should never happen as we just booked these blocks in this slot. + continue + } + + targetEngine.BlockGadget.SetAccepted(block) + + // Wait for all blocks to be notarized before forcing the commitment of the slot. + if notarizedBlocks.Add(-1) != 0 { + return + } + } + + // 3. Force commitment of the slot + producedCommitment, err := targetEngine.Notarization.ForceCommit(commitmentID.Slot()) + if err != nil { + b.protocol.HandleError(err) + return + } + + // 4. Verify that the produced commitment is the same as the initially requested one + if producedCommitment.ID() != commitmentID { + b.protocol.HandleError(ierrors.Errorf("producedCommitment ID mismatch: %s != %s", producedCommitment.ID(), commitmentID)) + return + } + } + for _, blockID := range blockIDs { - targetEngine.BlockDAG.GetOrRequestBlock(blockID) + block, _ := targetEngine.BlockDAG.GetOrRequestBlock(blockID) + if block == nil { // this should never happen as we're requesting the blocks for this slot so it can't be evicted. + continue + } + + block.Booked().OnUpdate(blockBookedCallback) } return nil diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index a87d53467..d38b95ecf 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -26,7 +26,7 @@ type Block struct { shallowLikeChildren []*Block // Booker block - booked bool + booked reactive.Variable[bool] witnesses ds.Set[account.SeatIndex] // conflictIDs are the all conflictIDs of the block inherited from the parents + payloadConflictIDs. conflictIDs ds.Set[iotago.TransactionID] @@ -47,6 +47,9 @@ type Block struct { enqueued bool dropped bool + // Notarization + notarized reactive.Variable[bool] + mutex syncutils.RWMutex modelBlock *model.Block @@ -99,13 +102,14 @@ func NewRootBlock(blockID iotago.BlockID, commitmentID iotago.CommitmentID, issu issuingTime: issuingTime, }, solid: true, - booked: true, + booked: reactive.NewVariable[bool](), preAccepted: true, accepted: reactive.NewVariable[bool](), scheduled: true, } // This should be true since we commit and evict on acceptance. + b.booked.Set(true) b.accepted.Set(true) return b @@ -358,22 +362,17 @@ func (b *Block) Update(data *model.Block) (wasPublished bool) { return true } -func (b *Block) IsBooked() (isBooked bool) { - b.mutex.RLock() - defer b.mutex.RUnlock() +// Booked returns a reactive variable that is true if the Block was booked. +func (b *Block) Booked() reactive.Variable[bool] { + return b.accepted +} - return b.booked +func (b *Block) IsBooked() (isBooked bool) { + return b.booked.Get() } func (b *Block) SetBooked() (wasUpdated bool) { - b.mutex.Lock() - defer b.mutex.Unlock() - - if wasUpdated = !b.booked; wasUpdated { - b.booked = true - } - - return + return !b.accepted.Set(true) } func (b *Block) AddWitness(seat account.SeatIndex) (added bool) { @@ -607,6 +606,18 @@ func (b *Block) SetPreConfirmed() (wasUpdated bool) { return wasUpdated } +func (b *Block) Notarized() reactive.Variable[bool] { + return b.notarized +} + +func (b *Block) IsNotarized() (isBooked bool) { + return b.notarized.Get() +} + +func (b *Block) SetNotarized() (wasUpdated bool) { + return !b.notarized.Set(true) +} + func (b *Block) String() string { b.mutex.RLock() defer b.mutex.RUnlock() @@ -627,6 +638,7 @@ func (b *Block) String() string { builder.AddField(stringify.NewStructField("Dropped", b.dropped)) builder.AddField(stringify.NewStructField("Skipped", b.skipped)) builder.AddField(stringify.NewStructField("Enqueued", b.enqueued)) + builder.AddField(stringify.NewStructField("Notarized", b.notarized.Get())) for index, child := range b.strongChildren { builder.AddField(stringify.NewStructField(fmt.Sprintf("strongChildren%d", index), child.ID().String())) diff --git a/pkg/protocol/engine/consensus/blockgadget/gadget.go b/pkg/protocol/engine/consensus/blockgadget/gadget.go index 2fe562c37..26d836832 100644 --- a/pkg/protocol/engine/consensus/blockgadget/gadget.go +++ b/pkg/protocol/engine/consensus/blockgadget/gadget.go @@ -9,4 +9,5 @@ type Gadget interface { module.Interface TrackWitnessWeight(votingBlock *blocks.Block) + SetAccepted(block *blocks.Block) bool } diff --git a/pkg/protocol/engine/consensus/blockgadget/thresholdblockgadget/acceptance_ratification.go b/pkg/protocol/engine/consensus/blockgadget/thresholdblockgadget/acceptance_ratification.go index 13466584e..e7bad633e 100644 --- a/pkg/protocol/engine/consensus/blockgadget/thresholdblockgadget/acceptance_ratification.go +++ b/pkg/protocol/engine/consensus/blockgadget/thresholdblockgadget/acceptance_ratification.go @@ -58,3 +58,12 @@ func (g *Gadget) shouldAccept(block *blocks.Block) bool { return votes.IsThresholdReached(blockSeats, onlineCommitteeTotalSeats, g.optsAcceptanceThreshold) } + +func (g *Gadget) SetAccepted(block *blocks.Block) bool { + if block.SetAccepted() { + g.events.BlockAccepted.Trigger(block) + return true + } + + return false +} diff --git a/pkg/protocol/engine/mempool/conflictdag/conflictdag.go b/pkg/protocol/engine/mempool/conflictdag/conflictdag.go index 2b60acc01..2513f6392 100644 --- a/pkg/protocol/engine/mempool/conflictdag/conflictdag.go +++ b/pkg/protocol/engine/mempool/conflictdag/conflictdag.go @@ -20,6 +20,7 @@ type ConflictDAG[ConflictID, ResourceID IDType, VoteRank VoteRankType[VoteRank]] ConflictingConflicts(conflictID ConflictID) (conflictingConflicts ds.Set[ConflictID], exists bool) CastVotes(vote *vote.Vote[VoteRank], conflictIDs ds.Set[ConflictID]) error AcceptanceState(conflictIDs ds.Set[ConflictID]) acceptance.State + SetAccepted(conflictID ConflictID) UnacceptedConflicts(conflictIDs ds.Set[ConflictID]) ds.Set[ConflictID] AllConflictsSupported(seat account.SeatIndex, conflictIDs ds.Set[ConflictID]) bool EvictConflict(conflictID ConflictID) diff --git a/pkg/protocol/engine/mempool/conflictdag/conflictdagv1/conflictdag.go b/pkg/protocol/engine/mempool/conflictdag/conflictdagv1/conflictdag.go index da09d98db..88306cc12 100644 --- a/pkg/protocol/engine/mempool/conflictdag/conflictdagv1/conflictdag.go +++ b/pkg/protocol/engine/mempool/conflictdag/conflictdagv1/conflictdag.go @@ -363,6 +363,15 @@ func (c *ConflictDAG[ConflictID, ResourceID, VoteRank]) AcceptanceState(conflict return lowestObservedState } +func (c *ConflictDAG[ConflictID, ResourceID, VoteRank]) SetAccepted(conflictID ConflictID) { + c.mutex.RLock() + defer c.mutex.RUnlock() + + if conflict, exists := c.conflictsByID.Get(conflictID); exists { + conflict.setAcceptanceState(acceptance.Accepted) + } +} + // UnacceptedConflicts takes a set of ConflictIDs and removes all the accepted Conflicts (leaving only the // pending or rejected ones behind). func (c *ConflictDAG[ConflictID, ResourceID, VoteRank]) UnacceptedConflicts(conflictIDs ds.Set[ConflictID]) ds.Set[ConflictID] { diff --git a/pkg/protocol/engine/notarization/notarization.go b/pkg/protocol/engine/notarization/notarization.go index 2a8d8c409..e137dd19e 100644 --- a/pkg/protocol/engine/notarization/notarization.go +++ b/pkg/protocol/engine/notarization/notarization.go @@ -2,11 +2,15 @@ package notarization import ( "github.com/iotaledger/hive.go/runtime/module" + "github.com/iotaledger/iota-core/pkg/model" + iotago "github.com/iotaledger/iota.go/v4" ) type Notarization interface { // IsBootstrapped returns if notarization finished committing all pending slots up to the current acceptance time. IsBootstrapped() bool + ForceCommit(slot iotago.SlotIndex) (*model.Commitment, error) + module.Interface } diff --git a/pkg/protocol/engine/notarization/slotnotarization/manager.go b/pkg/protocol/engine/notarization/slotnotarization/manager.go index 07976a75e..95a3be210 100644 --- a/pkg/protocol/engine/notarization/slotnotarization/manager.go +++ b/pkg/protocol/engine/notarization/slotnotarization/manager.go @@ -63,7 +63,9 @@ func NewProvider() module.Provider[*engine.Engine, notarization.Notarization] { if err := m.notarizeAcceptedBlock(block); err != nil { m.errorHandler(ierrors.Wrapf(err, "failed to add accepted block %s to slot", block.ID())) } - m.tryCommitUntil(block) + m.tryCommitUntil(block.ID().Slot()) + + block.SetNotarized() }, event.WithWorkerPool(wpBlocks)) e.Events.Notarization.LinkTo(m.events) @@ -92,10 +94,23 @@ func (m *Manager) Shutdown() { } // tryCommitUntil tries to create slot commitments until the new provided acceptance time. -func (m *Manager) tryCommitUntil(block *blocks.Block) { - if index := block.ID().Slot(); index > m.storage.Settings().LatestCommitment().Slot() { - m.tryCommitSlotUntil(index) +func (m *Manager) tryCommitUntil(commitUntilSlot iotago.SlotIndex) { + if slot := commitUntilSlot; slot > m.storage.Settings().LatestCommitment().Slot() { + m.tryCommitSlotUntil(slot) + } +} + +func (m *Manager) ForceCommit(slot iotago.SlotIndex) (*model.Commitment, error) { + if m.WasStopped() { + } + + commitment, err := m.createCommitment(slot) + if err != nil { + return nil, ierrors.Wrapf(err, "failed to create commitment for slot %d", slot) + } + + return commitment, nil } // IsBootstrapped returns if the Manager finished committing all pending slots up to the current acceptance time. @@ -127,7 +142,8 @@ func (m *Manager) tryCommitSlotUntil(acceptedBlockIndex iotago.SlotIndex) { return } - if !m.createCommitment(i) { + if _, err := m.createCommitment(i); err != nil { + m.errorHandler(ierrors.Wrapf(err, "failed to create commitment for slot %d", i)) return } } @@ -137,43 +153,37 @@ func (m *Manager) isCommittable(index, acceptedBlockIndex iotago.SlotIndex) bool return index+m.minCommittableAge <= acceptedBlockIndex } -func (m *Manager) createCommitment(index iotago.SlotIndex) (success bool) { +func (m *Manager) createCommitment(slot iotago.SlotIndex) (*model.Commitment, error) { latestCommitment := m.storage.Settings().LatestCommitment() - if index != latestCommitment.Slot()+1 { - m.errorHandler(ierrors.Errorf("cannot create commitment for slot %d, latest commitment is for slot %d", index, latestCommitment.Slot())) - return false + if slot != latestCommitment.Slot()+1 { + return nil, ierrors.Errorf("cannot create commitment for slot %d, latest commitment is for slot %d", slot, latestCommitment.Slot()) } // Set createIfMissing to true to make sure that this is never nil. Will get evicted later on anyway. - acceptedBlocks := m.slotMutations.AcceptedBlocks(index, true) + acceptedBlocks := m.slotMutations.AcceptedBlocks(slot, true) if err := acceptedBlocks.Commit(); err != nil { - m.errorHandler(ierrors.Wrap(err, "failed to commit accepted blocks")) - return false + return nil, ierrors.Wrap(err, "failed to commit accepted blocks") } - cumulativeWeight, attestationsRoot, err := m.attestation.Commit(index) + cumulativeWeight, attestationsRoot, err := m.attestation.Commit(slot) if err != nil { - m.errorHandler(ierrors.Wrap(err, "failed to commit attestations")) - return false + return nil, ierrors.Wrap(err, "failed to commit attestations") } - stateRoot, mutationRoot, accountRoot, err := m.ledger.CommitSlot(index) + stateRoot, mutationRoot, accountRoot, err := m.ledger.CommitSlot(slot) if err != nil { - m.errorHandler(ierrors.Wrap(err, "failed to commit ledger")) - return false + return nil, ierrors.Wrap(err, "failed to commit ledger") } - committeeRoot, rewardsRoot, err := m.sybilProtection.CommitSlot(index) + committeeRoot, rewardsRoot, err := m.sybilProtection.CommitSlot(slot) if err != nil { - m.errorHandler(ierrors.Wrap(err, "failed to commit sybil protection")) - return false + return nil, ierrors.Wrap(err, "failed to commit sybil protection") } - apiForSlot := m.apiProvider.APIForSlot(index) + apiForSlot := m.apiProvider.APIForSlot(slot) - protocolParametersAndVersionsHash, err := m.upgradeOrchestrator.Commit(index) + protocolParametersAndVersionsHash, err := m.upgradeOrchestrator.Commit(slot) if err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to commit protocol parameters and versions in upgrade orchestrator for slot %d", index)) - return false + return nil, ierrors.Wrapf(err, "failed to commit protocol parameters and versions in upgrade orchestrator for slot %d", slot) } roots := iotago.NewRoots( @@ -188,15 +198,14 @@ func (m *Manager) createCommitment(index iotago.SlotIndex) (success bool) { ) // calculate the new RMC - rmc, err := m.ledger.RMCManager().CommitSlot(index) + rmc, err := m.ledger.RMCManager().CommitSlot(slot) if err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to commit RMC for slot %d", index)) - return false + return nil, ierrors.Wrapf(err, "failed to commit RMC for slot %d", slot) } newCommitment := iotago.NewCommitment( apiForSlot.ProtocolParameters().Version(), - index, + slot, latestCommitment.ID(), roots.ID(), cumulativeWeight, @@ -205,22 +214,19 @@ func (m *Manager) createCommitment(index iotago.SlotIndex) (success bool) { newModelCommitment, err := model.CommitmentFromCommitment(newCommitment, apiForSlot, serix.WithValidation()) if err != nil { - return false + return nil, ierrors.Wrapf(err, "failed to create model commitment for commitment %s", newCommitment.MustID()) } - rootsStorage, err := m.storage.Roots(index) + rootsStorage, err := m.storage.Roots(slot) if err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed get roots storage for commitment %s", newModelCommitment.ID())) - return false + return nil, ierrors.Wrapf(err, "failed get roots storage for commitment %s", newModelCommitment.ID()) } if err = rootsStorage.Store(newModelCommitment.ID(), roots); err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to store latest roots for commitment %s", newModelCommitment.ID())) - return false + return nil, ierrors.Wrapf(err, "failed to store latest roots for commitment %s", newModelCommitment.ID()) } if err = m.storage.Commitments().Store(newModelCommitment); err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to store latest commitment %s", newModelCommitment.ID())) - return false + return nil, ierrors.Wrapf(err, "failed to store latest commitment %s", newModelCommitment.ID()) } m.events.SlotCommitted.Trigger(¬arization.SlotCommittedDetails{ @@ -230,17 +236,16 @@ func (m *Manager) createCommitment(index iotago.SlotIndex) (success bool) { }) if err = m.storage.Settings().SetLatestCommitment(newModelCommitment); err != nil { - m.errorHandler(ierrors.Wrap(err, "failed to set latest commitment")) - return false + return nil, ierrors.Wrap(err, "failed to set latest commitment") } m.events.LatestCommitmentUpdated.Trigger(newModelCommitment) - if err = m.slotMutations.Evict(index); err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to evict slotMutations at index: %d", index)) + if err = m.slotMutations.Evict(slot); err != nil { + m.errorHandler(ierrors.Wrapf(err, "failed to evict slotMutations at slot: %d", slot)) } - return true + return newModelCommitment, nil } var _ notarization.Notarization = new(Manager) From 1c8ce1746fca0551873353a451f046cc745e0c5c Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Wed, 20 Sep 2023 13:03:03 +0800 Subject: [PATCH 06/46] Store last issued validation block in settings --- pkg/blockfactory/blockissuer.go | 4 ++++ pkg/storage/permanent/settings.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/blockfactory/blockissuer.go b/pkg/blockfactory/blockissuer.go index e28603b3f..6c9857072 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -474,6 +474,10 @@ func (i *BlockIssuer) issueBlock(block *model.Block) error { return err } + if _, isValidationBlock := block.ValidationBlock(); isValidationBlock { + _ = i.protocol.MainEngineInstance().Storage.Settings().SetLatestIssuedValidationBlock(block) + } + i.events.BlockIssued.Trigger(block) return nil diff --git a/pkg/storage/permanent/settings.go b/pkg/storage/permanent/settings.go index ee6c44d16..6c63ffa15 100644 --- a/pkg/storage/permanent/settings.go +++ b/pkg/storage/permanent/settings.go @@ -25,6 +25,7 @@ const ( protocolVersionEpochMappingKey futureProtocolParametersKey protocolParametersKey + latestIssuedValidationBlock ) type Settings struct { @@ -33,6 +34,7 @@ type Settings struct { storeSnapshotImported *kvstore.TypedValue[bool] storeLatestCommitment *kvstore.TypedValue[*model.Commitment] storeLatestFinalizedSlot *kvstore.TypedValue[iotago.SlotIndex] + storeLatestIssuedValidationBlock *kvstore.TypedValue[*model.Block] storeProtocolVersionEpochMapping *kvstore.TypedStore[iotago.Version, iotago.EpochIndex] storeFutureProtocolParameters *kvstore.TypedStore[iotago.Version, *types.Tuple[iotago.EpochIndex, iotago.Identifier]] storeProtocolParameters *kvstore.TypedStore[iotago.Version, iotago.ProtocolParameters] @@ -299,6 +301,32 @@ func (s *Settings) latestFinalizedSlot() iotago.SlotIndex { return latestFinalizedSlot } +func (s *Settings) LatestIssuedValidationBlock() *model.Block { + s.mutex.RLock() + defer s.mutex.RUnlock() + + return s.latestIssuedValidationBlock() +} + +func (s *Settings) SetLatestIssuedValidationBlock(block *model.Block) (err error) { + s.mutex.Lock() + defer s.mutex.Unlock() + + return s.storeLatestIssuedValidationBlock.Set(block) +} + +func (s *Settings) latestIssuedValidationBlock() *model.Block { + block, err := s.storeLatestIssuedValidationBlock.Get() + if err != nil { + if ierrors.Is(err, kvstore.ErrKeyNotFound) { + return nil + } + panic(err) + } + + return block +} + func (s *Settings) Export(writer io.WriteSeeker, targetCommitment *iotago.Commitment) error { var commitmentBytes []byte var err error From e831a322a6429e599278d0e2dd6093c2bb5a0e5c Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Fri, 29 Sep 2023 11:10:48 +0200 Subject: [PATCH 07/46] Implement way to react to a halted chain in block issuer by introducing sentinel error if the latest commitment is > maxCommittableAge in the past --- pkg/blockfactory/acceptance_loss.go | 24 ++++++++++++++++++++++++ pkg/blockfactory/blockissuer.go | 7 ++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 pkg/blockfactory/acceptance_loss.go diff --git a/pkg/blockfactory/acceptance_loss.go b/pkg/blockfactory/acceptance_loss.go new file mode 100644 index 000000000..36cf80906 --- /dev/null +++ b/pkg/blockfactory/acceptance_loss.go @@ -0,0 +1,24 @@ +package blockfactory + +import ( + "github.com/iotaledger/iota-core/pkg/model" +) + +func (i *BlockIssuer) reviveChain(block *model.Block) error { + lastCommittedSlot := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Index() + apiForSlot := i.protocol.APIForSlot(lastCommittedSlot) + + // Get a parent from the last committed slot. + + // Get last issued block and start issuing after that subslot. + // TODO: also make sure to not issue on two distinct chains within the same slot. + lastIssuedBlockValidationBlock := i.protocol.MainEngineInstance().Storage.Settings().LatestIssuedValidationBlock() + if lastIssuedBlockValidationBlock != nil { + + } + + // Force commitments until minCommittableAge relative to the block's issuing time. We basically "pretend" that + // this block was already accepted at the time of issuing so that we have a commitment to reference. + + return nil +} diff --git a/pkg/blockfactory/blockissuer.go b/pkg/blockfactory/blockissuer.go index 6c9857072..69c6b9bff 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -24,6 +24,7 @@ var ( ErrBlockAttacherInvalidBlock = ierrors.New("invalid block") ErrBlockAttacherAttachingNotPossible = ierrors.New("attaching not possible") ErrBlockAttacherIncompleteBlockNotAllowed = ierrors.New("incomplete block is not allowed on this node") + ErrBlockTooRecent = ierrors.New("block is too recent compared to latest commitment") ) // TODO: make sure an honest validator does not issue blocks within the same slot ratification period in two conflicting chains. @@ -77,6 +78,10 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, issuerAccount A } if err := i.setDefaultBlockParams(blockParams.BlockHeader, issuerAccount); err != nil { + if ierrors.Is(err, ErrBlockTooRecent) { + // TODO: revive chain + } + return nil, err } @@ -422,7 +427,7 @@ func (i *BlockIssuer) getCommitment(blockSlot iotago.SlotIndex) (*iotago.Commitm commitment := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment() if blockSlot > commitment.Slot+protoParams.MaxCommittableAge() { - return nil, ierrors.Errorf("can't issue block: block slot %d is too far in the future, latest commitment is %d", blockSlot, commitment.Slot) + return nil, ierrors.Wrapf(ErrBlockTooRecent, "can't issue block: block slot %d is too far in the future, latest commitment is %d", blockSlot, commitment.Slot) } if blockSlot < commitment.Slot+protoParams.MinCommittableAge() { From c3f821dae4d78a9a665528ea8097ffec1eedf31a Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Fri, 29 Sep 2023 13:51:19 +0200 Subject: [PATCH 08/46] Add revive chain to block issuer --- pkg/blockfactory/acceptance_loss.go | 38 ++++++++++++++++-- pkg/blockfactory/blockissuer.go | 40 ++++++++++--------- pkg/model/block.go | 15 +++++++ pkg/protocol/block_dispatcher.go | 8 ++-- pkg/protocol/engine/blocks/block.go | 1 + .../engine/notarization/notarization.go | 1 + .../notarization/slotnotarization/manager.go | 12 +++++- pkg/storage/permanent/settings.go | 6 +++ pkg/tests/loss_of_acceptance_test.go | 36 +++++++++++++++++ 9 files changed, 129 insertions(+), 28 deletions(-) create mode 100644 pkg/tests/loss_of_acceptance_test.go diff --git a/pkg/blockfactory/acceptance_loss.go b/pkg/blockfactory/acceptance_loss.go index 36cf80906..7bf746c97 100644 --- a/pkg/blockfactory/acceptance_loss.go +++ b/pkg/blockfactory/acceptance_loss.go @@ -1,14 +1,30 @@ package blockfactory import ( - "github.com/iotaledger/iota-core/pkg/model" + "time" + + "github.com/iotaledger/hive.go/ierrors" + iotago "github.com/iotaledger/iota.go/v4" ) -func (i *BlockIssuer) reviveChain(block *model.Block) error { - lastCommittedSlot := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Index() +func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, iotago.BlockID, error) { + lastCommittedSlot := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() apiForSlot := i.protocol.APIForSlot(lastCommittedSlot) // Get a parent from the last committed slot. + store, err := i.protocol.MainEngineInstance().Storage.Blocks(lastCommittedSlot) + if err != nil { + return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to get blocks for slot %d", lastCommittedSlot) + } + + expectedErr := ierrors.New("stop iteration") + parentBlockID := iotago.EmptyBlockID() + if err = store.StreamKeys(func(blockID iotago.BlockID) error { + parentBlockID = blockID + return expectedErr + }); err != nil && !ierrors.Is(err, expectedErr) { + return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to stream block IDs for slot %d", lastCommittedSlot) + } // Get last issued block and start issuing after that subslot. // TODO: also make sure to not issue on two distinct chains within the same slot. @@ -16,9 +32,23 @@ func (i *BlockIssuer) reviveChain(block *model.Block) error { if lastIssuedBlockValidationBlock != nil { } + issuingSlot := apiForSlot.TimeProvider().SlotFromTime(issuingTime) // Force commitments until minCommittableAge relative to the block's issuing time. We basically "pretend" that // this block was already accepted at the time of issuing so that we have a commitment to reference. + if issuingSlot < apiForSlot.ProtocolParameters().MinCommittableAge() { // Should never happen as we're beyond maxCommittableAge which is > minCommittableAge. + return nil, iotago.EmptyBlockID(), ierrors.Errorf("issuing slot %d is smaller than min committable age %d", issuingSlot, apiForSlot.ProtocolParameters().MinCommittableAge()) + } + commitUntilSlot := issuingSlot - apiForSlot.ProtocolParameters().MinCommittableAge() + + if err = i.protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { + return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to force commit until slot %d", commitUntilSlot) + } + + commitment, err := i.protocol.MainEngineInstance().Storage.Commitments().Load(commitUntilSlot) + if err != nil { + return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to load commitment for slot %d", commitUntilSlot) + } - return nil + return commitment.Commitment(), parentBlockID, nil } diff --git a/pkg/blockfactory/blockissuer.go b/pkg/blockfactory/blockissuer.go index 69c6b9bff..2611100fc 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -68,6 +68,27 @@ func (i *BlockIssuer) Shutdown() { func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, issuerAccount Account, opts ...options.Option[ValidatorBlockParams]) (*model.Block, error) { blockParams := options.Apply(&ValidatorBlockParams{}, opts) + if blockParams.BlockHeader.IssuingTime == nil { + issuingTime := time.Now().UTC() + blockParams.BlockHeader.IssuingTime = &issuingTime + } + + if blockParams.BlockHeader.SlotCommitment == nil { + var err error + blockParams.BlockHeader.SlotCommitment, err = i.getCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) + if err != nil && ierrors.Is(err, ErrBlockTooRecent) { + commitment, parentID, err := i.reviveChain(*blockParams.BlockHeader.IssuingTime) + if err != nil { + return nil, ierrors.Wrap(err, "failed to revive chain") + } + blockParams.BlockHeader.SlotCommitment = commitment + blockParams.BlockHeader.References[iotago.StrongParentType] = []iotago.BlockID{parentID} + + } else if err != nil { + return nil, ierrors.Wrap(err, "error getting commitment") + } + } + if blockParams.BlockHeader.References == nil { // TODO: change this to get references for validator block references, err := i.getReferences(ctx, nil, blockParams.BlockHeader.ParentsCount) @@ -78,11 +99,7 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, issuerAccount A } if err := i.setDefaultBlockParams(blockParams.BlockHeader, issuerAccount); err != nil { - if ierrors.Is(err, ErrBlockTooRecent) { - // TODO: revive chain - } - - return nil, err + return nil, ierrors.Wrap(err, "error setting default block params") } if blockParams.HighestSupportedVersion == nil { @@ -391,19 +408,6 @@ func (i *BlockIssuer) AttachBlock(ctx context.Context, iotaBlock *iotago.Protoco } func (i *BlockIssuer) setDefaultBlockParams(blockParams *BlockHeaderParams, issuerAccount Account) error { - if blockParams.IssuingTime == nil { - issuingTime := time.Now().UTC() - blockParams.IssuingTime = &issuingTime - } - - if blockParams.SlotCommitment == nil { - var err error - blockParams.SlotCommitment, err = i.getCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.IssuingTime)) - if err != nil { - return ierrors.Wrap(err, "error getting commitment") - } - } - if blockParams.LatestFinalizedSlot == nil { latestFinalizedSlot := i.protocol.MainEngineInstance().Storage.Settings().LatestFinalizedSlot() blockParams.LatestFinalizedSlot = &latestFinalizedSlot diff --git a/pkg/model/block.go b/pkg/model/block.go index 557f715d0..d5c212153 100644 --- a/pkg/model/block.go +++ b/pkg/model/block.go @@ -62,6 +62,17 @@ func BlockFromBytes(data []byte, apiProvider iotago.APIProvider) (*Block, error) return newBlock(blockID, iotaBlock, data) } +func BlockFromBytesFunc(apiProvider iotago.APIProvider) func(data []byte) (*Block, int, error) { + return func(data []byte) (*Block, int, error) { + block, err := BlockFromBytes(data, apiProvider) + if err != nil { + return nil, 0, err + } + + return block, len(data), nil + } +} + func (blk *Block) ID() iotago.BlockID { return blk.blockID } @@ -70,6 +81,10 @@ func (blk *Block) Data() []byte { return blk.data } +func (blk *Block) Bytes() ([]byte, error) { + return blk.data, nil +} + func (blk *Block) ProtocolBlock() *iotago.ProtocolBlock { return blk.protocolBlock } diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 5fa9f1b88..c6632f6c8 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -238,14 +238,12 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment // 1. Mark all transactions as accepted // 2. Mark all blocks as accepted // 3. Force commitment of the slot + totalBlocks := uint32(len(blockIDs)) var bookedBlocks atomic.Uint32 - bookedBlocks.Store(uint32(len(blockIDs))) - var notarizedBlocks atomic.Uint32 - notarizedBlocks.Store(uint32(len(blockIDs))) blockBookedCallback := func(_, _ bool) { - if bookedBlocks.Add(-1) != 0 { + if bookedBlocks.Add(1) != totalBlocks { return } @@ -264,7 +262,7 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment targetEngine.BlockGadget.SetAccepted(block) // Wait for all blocks to be notarized before forcing the commitment of the slot. - if notarizedBlocks.Add(-1) != 0 { + if notarizedBlocks.Add(1) != totalBlocks { return } } diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index d38b95ecf..602e81545 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -83,6 +83,7 @@ func NewBlock(data *model.Block) *Block { acceptanceRatifiers: ds.NewSet[account.SeatIndex](), confirmationRatifiers: ds.NewSet[account.SeatIndex](), modelBlock: data, + booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), workScore: data.WorkScore(), } diff --git a/pkg/protocol/engine/notarization/notarization.go b/pkg/protocol/engine/notarization/notarization.go index e137dd19e..78c3dd88f 100644 --- a/pkg/protocol/engine/notarization/notarization.go +++ b/pkg/protocol/engine/notarization/notarization.go @@ -11,6 +11,7 @@ type Notarization interface { IsBootstrapped() bool ForceCommit(slot iotago.SlotIndex) (*model.Commitment, error) + ForceCommitUntil(commitUntilSlot iotago.SlotIndex) error module.Interface } diff --git a/pkg/protocol/engine/notarization/slotnotarization/manager.go b/pkg/protocol/engine/notarization/slotnotarization/manager.go index 95a3be210..ec560d1cb 100644 --- a/pkg/protocol/engine/notarization/slotnotarization/manager.go +++ b/pkg/protocol/engine/notarization/slotnotarization/manager.go @@ -102,7 +102,7 @@ func (m *Manager) tryCommitUntil(commitUntilSlot iotago.SlotIndex) { func (m *Manager) ForceCommit(slot iotago.SlotIndex) (*model.Commitment, error) { if m.WasStopped() { - + return nil, ierrors.New("notarization manager was stopped") } commitment, err := m.createCommitment(slot) @@ -113,6 +113,16 @@ func (m *Manager) ForceCommit(slot iotago.SlotIndex) (*model.Commitment, error) return commitment, nil } +func (m *Manager) ForceCommitUntil(commitUntilSlot iotago.SlotIndex) error { + for i := m.storage.Settings().LatestCommitment().Slot() + 1; i <= commitUntilSlot; i++ { + if _, err := m.ForceCommit(i); err != nil { + return ierrors.Wrapf(err, "failed to force commit slot %d", i) + } + } + + return nil +} + // IsBootstrapped returns if the Manager finished committing all pending slots up to the current acceptance time. func (m *Manager) IsBootstrapped() bool { // If acceptance time is somewhere in the middle of slot 10, then the latest committable index is 4 (with minCommittableAge=6), diff --git a/pkg/storage/permanent/settings.go b/pkg/storage/permanent/settings.go index 6c63ffa15..3298beffe 100644 --- a/pkg/storage/permanent/settings.go +++ b/pkg/storage/permanent/settings.go @@ -83,6 +83,12 @@ func NewSettings(store kvstore.KVStore, opts ...options.Option[api.EpochBasedPro iotago.SlotIndex.Bytes, iotago.SlotIndexFromBytes, ), + storeLatestIssuedValidationBlock: kvstore.NewTypedValue( + store, + []byte{latestIssuedValidationBlock}, + (*model.Block).Bytes, + model.BlockFromBytesFunc(apiProvider), + ), storeProtocolVersionEpochMapping: kvstore.NewTypedStore( lo.PanicOnErr(store.WithExtendedRealm([]byte{protocolVersionEpochMappingKey})), diff --git a/pkg/tests/loss_of_acceptance_test.go b/pkg/tests/loss_of_acceptance_test.go new file mode 100644 index 000000000..78a5ea674 --- /dev/null +++ b/pkg/tests/loss_of_acceptance_test.go @@ -0,0 +1,36 @@ +package tests + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/iotaledger/iota-core/pkg/blockfactory" + "github.com/iotaledger/iota-core/pkg/testsuite" +) + +func TestLossOfAcceptanceFromGenesis(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(4), + testsuite.WithEpochNearingThreshold(2), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(100*10), + ) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + + ts.Run(true, nil) + + block0 := ts.IssueValidationBlock("block0", node0, + blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), + blockfactory.WithStrongParents(ts.BlockIDs("Genesis")...), + ) + require.EqualValues(t, 48, block0.SlotCommitmentID().Slot()) + + ts.AssertLatestCommitmentSlotIndex(48, ts.Nodes()...) + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes()...) +} From 3f4b071ece2f968ecd157de64c9232906e889f20 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:03:09 +0200 Subject: [PATCH 09/46] Extend loss of acceptance test to have other nodes warp sync empty and non-empty slots --- pkg/tests/loss_of_acceptance_test.go | 44 ++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/pkg/tests/loss_of_acceptance_test.go b/pkg/tests/loss_of_acceptance_test.go index 78a5ea674..d4c081320 100644 --- a/pkg/tests/loss_of_acceptance_test.go +++ b/pkg/tests/loss_of_acceptance_test.go @@ -1,12 +1,16 @@ package tests import ( + "fmt" "testing" + "time" "github.com/stretchr/testify/require" "github.com/iotaledger/iota-core/pkg/blockfactory" + "github.com/iotaledger/iota-core/pkg/protocol" "github.com/iotaledger/iota-core/pkg/testsuite" + iotago "github.com/iotaledger/iota.go/v4" ) func TestLossOfAcceptanceFromGenesis(t *testing.T) { @@ -22,15 +26,49 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { defer ts.Shutdown() node0 := ts.AddValidatorNode("node0") + ts.AddValidatorNode("node1") + ts.AddNode("node2") ts.Run(true, nil) - block0 := ts.IssueValidationBlock("block0", node0, + // Create snapshot to use later. + snapshotPath := ts.Directory.Path(fmt.Sprintf("%d_snapshot", time.Now().Unix())) + require.NoError(t, ts.Node("node0").Protocol.MainEngineInstance().WriteSnapshot(snapshotPath)) + + ts.IssueValidationBlock("block0", node0, blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), blockfactory.WithStrongParents(ts.BlockIDs("Genesis")...), ) - require.EqualValues(t, 48, block0.SlotCommitmentID().Slot()) + require.EqualValues(t, 48, ts.Block("block0").SlotCommitmentID().Slot()) + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0")...) + + // Need to issue to slot 52 so that all other nodes can warp sync up to slot 49 and then commit slot 50 themselves. + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{51, 52}, 2, "block0", ts.Nodes("node0"), true, nil) - ts.AssertLatestCommitmentSlotIndex(48, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(50, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(50, ts.Nodes()...) ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes()...) + + // Continue issuing on all nodes for a few slots. + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{53, 54, 55, 56, 57}, 3, "52.1", ts.Nodes(), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(55, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(55, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("57.0"), true, ts.Nodes()...) + + { + node3 := ts.AddNode("node3") + node3.Initialize(true, + protocol.WithSnapshotPath(snapshotPath), + protocol.WithBaseDirectory(ts.Directory.PathWithCreate(node3.Name)), + ) + ts.Wait() + } + + // Continue issuing on all nodes for a few slots. + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{58}, 3, "57.2", ts.Nodes("node0", "node1", "node2"), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(56, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(56, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("58.0"), true, ts.Nodes()...) } From 9096d47d7608ddb7c99f7f044cc030105e0bc3cd Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:04:19 +0200 Subject: [PATCH 10/46] Fix basic block issuing nil pointer --- pkg/blockfactory/blockissuer.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/blockfactory/blockissuer.go b/pkg/blockfactory/blockissuer.go index 2611100fc..c3c7f2918 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -174,6 +174,19 @@ func (i *BlockIssuer) retrieveAPI(blockParams *BlockHeaderParams) (iotago.API, e func (i *BlockIssuer) CreateBlock(ctx context.Context, issuerAccount Account, opts ...options.Option[BasicBlockParams]) (*model.Block, error) { blockParams := options.Apply(&BasicBlockParams{}, opts) + if blockParams.BlockHeader.IssuingTime == nil { + issuingTime := time.Now().UTC() + blockParams.BlockHeader.IssuingTime = &issuingTime + } + + if blockParams.BlockHeader.SlotCommitment == nil { + var err error + blockParams.BlockHeader.SlotCommitment, err = i.getCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) + if err != nil { + return nil, ierrors.Wrap(err, "error getting commitment") + } + } + if blockParams.BlockHeader.References == nil { references, err := i.getReferences(ctx, blockParams.Payload, blockParams.BlockHeader.ParentsCount) if err != nil { From 7b90ad689ab009321c1d7c950f7f4c3c9bd6cfbd Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:05:00 +0200 Subject: [PATCH 11/46] Fix not correctly initialized reactive variables in blocks.Block --- pkg/protocol/engine/blocks/block.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index 602e81545..32c005d13 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -85,6 +85,7 @@ func NewBlock(data *model.Block) *Block { modelBlock: data, booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), + notarized: reactive.NewVariable[bool](), workScore: data.WorkScore(), } } @@ -106,6 +107,7 @@ func NewRootBlock(blockID iotago.BlockID, commitmentID iotago.CommitmentID, issu booked: reactive.NewVariable[bool](), preAccepted: true, accepted: reactive.NewVariable[bool](), + notarized: reactive.NewVariable[bool](), scheduled: true, } @@ -125,7 +127,9 @@ func NewMissingBlock(blockID iotago.BlockID) *Block { payloadConflictIDs: ds.NewSet[iotago.TransactionID](), acceptanceRatifiers: ds.NewSet[account.SeatIndex](), confirmationRatifiers: ds.NewSet[account.SeatIndex](), + booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), + notarized: reactive.NewVariable[bool](), } } @@ -365,7 +369,7 @@ func (b *Block) Update(data *model.Block) (wasPublished bool) { // Booked returns a reactive variable that is true if the Block was booked. func (b *Block) Booked() reactive.Variable[bool] { - return b.accepted + return b.booked } func (b *Block) IsBooked() (isBooked bool) { @@ -373,7 +377,7 @@ func (b *Block) IsBooked() (isBooked bool) { } func (b *Block) SetBooked() (wasUpdated bool) { - return !b.accepted.Set(true) + return !b.booked.Set(true) } func (b *Block) AddWitness(seat account.SeatIndex) (added bool) { @@ -627,7 +631,7 @@ func (b *Block) String() string { builder.AddField(stringify.NewStructField("Missing", b.missing)) builder.AddField(stringify.NewStructField("Solid", b.solid)) builder.AddField(stringify.NewStructField("Invalid", b.invalid)) - builder.AddField(stringify.NewStructField("Booked", b.booked)) + builder.AddField(stringify.NewStructField("Booked", b.booked.Get())) builder.AddField(stringify.NewStructField("Witnesses", b.witnesses)) builder.AddField(stringify.NewStructField("PreAccepted", b.preAccepted)) builder.AddField(stringify.NewStructField("AcceptanceRatifiers", b.acceptanceRatifiers.String())) From f173ff5b5dc1a967e35bc653f0fc32366b70b799 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:06:25 +0200 Subject: [PATCH 12/46] Make sure that blocks whose commitments is known but not in sync window for the engine are buffered in the commitment buffer --- pkg/protocol/block_dispatcher.go | 6 ++++++ pkg/protocol/engine/engine.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index c6632f6c8..460ebc822 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -85,6 +85,12 @@ func (b *BlockDispatcher) Dispatch(block *model.Block, src peer.ID) error { if engine != nil && (engine.ChainID() == slotCommitment.Chain().ForkingPoint.ID() || engine.BlockRequester.HasTicker(block.ID())) { if b.inSyncWindow(engine, block) { engine.ProcessBlockFromPeer(block, src) + } else { + // Stick too new blocks into the unsolid commitment buffer so that they can be dispatched once the + // engine instance is in sync (mostly needed for tests). + if !b.unsolidCommitmentBlocks.Add(slotCommitment.ID(), types.NewTuple(block, src)) { + return ierrors.Errorf("failed to add block %s to unsolid commitment buffer", block.ID()) + } } matchingEngineFound = true diff --git a/pkg/protocol/engine/engine.go b/pkg/protocol/engine/engine.go index f5dca917d..a5e0087c3 100644 --- a/pkg/protocol/engine/engine.go +++ b/pkg/protocol/engine/engine.go @@ -518,7 +518,7 @@ func (e *Engine) EarliestRootCommitment(lastFinalizedSlot iotago.SlotIndex) (ear rootCommitment, err := e.Storage.Commitments().Load(earliestRootCommitmentSlot) if err != nil { - panic(fmt.Sprintln("could not load earliest commitment after engine initialization", err)) + panic(fmt.Sprintf("could not load earliest commitment %d after engine initialization: %s", earliestRootCommitmentSlot, err)) } return rootCommitment From 8efab21810d71bf592599ca5617877d20d7918b9 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:08:08 +0200 Subject: [PATCH 13/46] Do not process already committed slots in warpsync again if the commitment has already been evicted --- pkg/protocol/block_dispatcher.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 460ebc822..686d37a29 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -218,6 +218,12 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment return ierrors.Errorf("failed to get target engine for %s", commitmentID) } + // Make sure that already evicted commitments are not processed. This might happen if there's a lot of slots to process ] + // and old responses are still in the task queue. + if loadedCommitment, err := targetEngine.Storage.Commitments().Load(commitmentID.Slot()); err == nil && loadedCommitment.ID() == commitmentID { + return nil + } + acceptedBlocks := ads.NewSet[iotago.BlockID](mapdb.NewMapDB(), iotago.BlockID.Bytes, iotago.SlotIdentifierFromBytes) for _, blockID := range blockIDs { _ = acceptedBlocks.Add(blockID) // a mapdb can never return an error From c8dccbab2192f1fa96cf17cafc75a7d6504e7ee7 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:14:14 +0200 Subject: [PATCH 14/46] Force commitment also for empty slots and set warp sync range to 1 --- pkg/protocol/block_dispatcher.go | 51 ++++++++++++++------------------ 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 686d37a29..b6ee5af74 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -13,7 +13,6 @@ import ( "github.com/iotaledger/hive.go/ds/types" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/kvstore/mapdb" - "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/options" "github.com/iotaledger/hive.go/runtime/workerpool" "github.com/iotaledger/iota-core/pkg/core/buffer" @@ -47,9 +46,6 @@ type BlockDispatcher struct { // shutdownEvent is a reactive event that is triggered when the BlockDispatcher instance is stopped. shutdownEvent reactive.Event - - // optWarpSyncWindowSize is the optional warp sync window size. - optWarpSyncWindowSize iotago.SlotIndex } // NewBlockDispatcher creates a new BlockDispatcher instance. @@ -254,7 +250,22 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment var bookedBlocks atomic.Uint32 var notarizedBlocks atomic.Uint32 - blockBookedCallback := func(_, _ bool) { + forceCommitmentFunc := func() { + // 3. Force commitment of the slot + producedCommitment, err := targetEngine.Notarization.ForceCommit(commitmentID.Slot()) + if err != nil { + b.protocol.HandleError(err) + return + } + + // 4. Verify that the produced commitment is the same as the initially requested one + if producedCommitment.ID() != commitmentID { + b.protocol.HandleError(ierrors.Errorf("producedCommitment ID mismatch: %s != %s", producedCommitment.ID(), commitmentID)) + return + } + } + + blockBookedFunc := func(_, _ bool) { if bookedBlocks.Add(1) != totalBlocks { return } @@ -277,20 +288,14 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment if notarizedBlocks.Add(1) != totalBlocks { return } - } - // 3. Force commitment of the slot - producedCommitment, err := targetEngine.Notarization.ForceCommit(commitmentID.Slot()) - if err != nil { - b.protocol.HandleError(err) - return + forceCommitmentFunc() } + } - // 4. Verify that the produced commitment is the same as the initially requested one - if producedCommitment.ID() != commitmentID { - b.protocol.HandleError(ierrors.Errorf("producedCommitment ID mismatch: %s != %s", producedCommitment.ID(), commitmentID)) - return - } + if len(blockIDs) == 0 { + forceCommitmentFunc() + return nil } for _, blockID := range blockIDs { @@ -299,7 +304,7 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment continue } - block.Booked().OnUpdate(blockBookedCallback) + block.Booked().OnUpdate(blockBookedFunc) } return nil @@ -334,10 +339,7 @@ func (b *BlockDispatcher) warpSyncIfNecessary(e *engine.Engine, chainCommitment return } - maxCommittableAge := e.APIForSlot(chainCommitment.Commitment().Slot()).ProtocolParameters().MaxCommittableAge() - warpSyncWindowSize := lo.Max(maxCommittableAge, b.optWarpSyncWindowSize) - - for slotToWarpSync := latestCommitmentSlot + 1; slotToWarpSync <= latestCommitmentSlot+warpSyncWindowSize; slotToWarpSync++ { + for slotToWarpSync := latestCommitmentSlot + 1; slotToWarpSync <= latestCommitmentSlot+1; slotToWarpSync++ { commitmentToSync := chain.Commitment(slotToWarpSync) if commitmentToSync == nil { break @@ -420,12 +422,5 @@ func (b *BlockDispatcher) runTask(task func(), pool *workerpool.WorkerPool) { }) } -// WithWarpSyncWindowSize is an option for the BlockDispatcher that allows to set the warp sync window size. -func WithWarpSyncWindowSize(windowSize iotago.SlotIndex) options.Option[BlockDispatcher] { - return func(b *BlockDispatcher) { - b.optWarpSyncWindowSize = windowSize - } -} - // WarpSyncRetryInterval is the interval in which a warp sync request is retried. const WarpSyncRetryInterval = 1 * time.Minute From ce57187629b9e15735cc1cd7ca1595e8a022b9de Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:27:36 +0200 Subject: [PATCH 15/46] Fix waiting for blocks to become notarized so that attestations can be included properly --- pkg/protocol/block_dispatcher.go | 12 +++++++----- pkg/testsuite/mock/node.go | 10 +++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index b6ee5af74..13d009346 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -284,12 +284,14 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment targetEngine.BlockGadget.SetAccepted(block) - // Wait for all blocks to be notarized before forcing the commitment of the slot. - if notarizedBlocks.Add(1) != totalBlocks { - return - } + block.Notarized().OnUpdate(func(_, _ bool) { + // Wait for all blocks to be notarized before forcing the commitment of the slot. + if notarizedBlocks.Add(1) != totalBlocks { + return + } - forceCommitmentFunc() + forceCommitmentFunc() + }) } } diff --git a/pkg/testsuite/mock/node.go b/pkg/testsuite/mock/node.go index ec7615611..9ebf01a75 100644 --- a/pkg/testsuite/mock/node.go +++ b/pkg/testsuite/mock/node.go @@ -180,17 +180,17 @@ func (n *Node) hookLogging(failOnBlockFiltered bool) { fmt.Printf("%s > Network.AttestationsRequestReceived: from %s %s\n", n.Name, source, id) }) - //events.ChainManager.CommitmentBelowRoot.Hook(func(commitmentID iotago.CommitmentID) { + // events.ChainManager.CommitmentBelowRoot.Hook(func(commitmentID iotago.CommitmentID) { // fmt.Printf("%s > ChainManager.CommitmentBelowRoot: %s\n", n.Name, commitmentID) - //}) + // }) events.ChainManager.ForkDetected.Hook(func(fork *chainmanager.Fork) { fmt.Printf("%s > ChainManager.ForkDetected: %s\n", n.Name, fork) }) - //events.Engine.TipManager.BlockAdded.Hook(func(tipMetadata tipmanager.TipMetadata) { + // events.Engine.TipManager.BlockAdded.Hook(func(tipMetadata tipmanager.TipMetadata) { // fmt.Printf("%s > TipManager.BlockAdded: %s in pool %d\n", n.Name, tipMetadata.ID(), tipMetadata.TipPool().Get()) - //}) + // }) events.CandidateEngineActivated.Hook(func(e *engine.Engine) { fmt.Printf("%s > CandidateEngineActivated: %s, ChainID:%s Slot:%s\n", n.Name, e.Name(), e.ChainID(), e.ChainID().Slot()) @@ -332,7 +332,7 @@ func (n *Node) attachEngineLogs(failOnBlockFiltered bool, instance *engine.Engin require.NoError(n.Testing, err) } - fmt.Printf("%s > [%s] NotarizationManager.SlotCommitted: %s %s %s %s %s\n", n.Name, engineName, details.Commitment.ID(), details.Commitment, acceptedBlocks, roots, attestationBlockIDs) + fmt.Printf("%s > [%s] NotarizationManager.SlotCommitted: %s %s Accepted Blocks: %s\n %s\n Attestations: %s\n", n.Name, engineName, details.Commitment.ID(), details.Commitment, acceptedBlocks, roots, attestationBlockIDs) }) events.Notarization.LatestCommitmentUpdated.Hook(func(commitment *model.Commitment) { From 90ef4a2e29cd4cdac23c6bb4adb7ce1094269164 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:28:26 +0200 Subject: [PATCH 16/46] Set blocks synced with warp sync as root blocks as otherwise we could not sync following slots anymore --- pkg/protocol/block_dispatcher.go | 5 +++++ pkg/protocol/engine/blocks/block.go | 1 + 2 files changed, 6 insertions(+) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 13d009346..84194f3a5 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -306,6 +306,11 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment continue } + // We need to make sure that we add all blocks as root blocks because we don't know which blocks are root blocks without + // blocks from future slots. We're committing the current slot which then leads to the eviction of the blocks from the + // block cache and thus if not root blocks no block in the next slot can become solid. + targetEngine.EvictionState.AddRootBlock(block.ID(), block.SlotCommitmentID()) + block.Booked().OnUpdate(blockBookedFunc) } diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index 32c005d13..4d31deb55 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -113,6 +113,7 @@ func NewRootBlock(blockID iotago.BlockID, commitmentID iotago.CommitmentID, issu // This should be true since we commit and evict on acceptance. b.booked.Set(true) + b.notarized.Set(true) b.accepted.Set(true) return b From 4222336d1e7038a6653aab95aebf46fc6cdd3860 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Sun, 1 Oct 2023 18:52:16 +0200 Subject: [PATCH 17/46] Fix loss of acceptance test and continue issuing for 2 slots so that new joining nodes can always warp sync --- pkg/protocol/block_dispatcher.go | 3 +++ pkg/tests/loss_of_acceptance_test.go | 8 ++++---- pkg/testsuite/mock/node.go | 8 ++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 84194f3a5..eae2bd7de 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -342,6 +342,9 @@ func (b *BlockDispatcher) warpSyncIfNecessary(e *engine.Engine, chainCommitment chain := chainCommitment.Chain() latestCommitmentSlot := e.Storage.Settings().LatestCommitment().Slot() + // We don't want to warpsync if the latest commitment of the engine is very close to the latest commitment of the + // chain as the node might just be about to commit it itself. This is important for tests, as we always need to issue + // 2 slots ahead of the latest commitment of the chain to make sure that the other nodes can warp sync. if latestCommitmentSlot+1 >= chain.LatestCommitment().Commitment().Slot() { return } diff --git a/pkg/tests/loss_of_acceptance_test.go b/pkg/tests/loss_of_acceptance_test.go index d4c081320..8235447db 100644 --- a/pkg/tests/loss_of_acceptance_test.go +++ b/pkg/tests/loss_of_acceptance_test.go @@ -66,9 +66,9 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { } // Continue issuing on all nodes for a few slots. - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{58}, 3, "57.2", ts.Nodes("node0", "node1", "node2"), true, nil) + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{58, 59}, 3, "57.2", ts.Nodes("node0", "node1", "node2"), true, nil) - ts.AssertEqualStoredCommitmentAtIndex(56, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(56, ts.Nodes()...) - ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("58.0"), true, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(57, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(57, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("59.0"), true, ts.Nodes()...) } diff --git a/pkg/testsuite/mock/node.go b/pkg/testsuite/mock/node.go index 9ebf01a75..5ffe01254 100644 --- a/pkg/testsuite/mock/node.go +++ b/pkg/testsuite/mock/node.go @@ -180,6 +180,14 @@ func (n *Node) hookLogging(failOnBlockFiltered bool) { fmt.Printf("%s > Network.AttestationsRequestReceived: from %s %s\n", n.Name, source, id) }) + events.Network.WarpSyncResponseReceived.Hook(func(id iotago.CommitmentID, ds iotago.BlockIDs, m *merklehasher.Proof[iotago.Identifier], ds2 iotago.TransactionIDs, m2 *merklehasher.Proof[iotago.Identifier], id2 peer.ID) { + fmt.Printf("%s > Network.WarpSyncResponseReceived: from %s %s\n", n.Name, id2, id) + }) + + events.Network.WarpSyncRequestReceived.Hook(func(id iotago.CommitmentID, id2 peer.ID) { + fmt.Printf("%s > Network.WarpSyncRequestReceived: from %s %s\n", n.Name, id2, id) + }) + // events.ChainManager.CommitmentBelowRoot.Hook(func(commitmentID iotago.CommitmentID) { // fmt.Printf("%s > ChainManager.CommitmentBelowRoot: %s\n", n.Name, commitmentID) // }) From cbca09e56f8bddd4289fb872fd596adda166204d Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:01:06 +0200 Subject: [PATCH 18/46] Take a parent block from root blocks when reviving the chain --- pkg/blockfactory/acceptance_loss.go | 22 ++++++++++------------ pkg/blockfactory/blockissuer.go | 1 + 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/pkg/blockfactory/acceptance_loss.go b/pkg/blockfactory/acceptance_loss.go index 7bf746c97..188847211 100644 --- a/pkg/blockfactory/acceptance_loss.go +++ b/pkg/blockfactory/acceptance_loss.go @@ -12,18 +12,16 @@ func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, io apiForSlot := i.protocol.APIForSlot(lastCommittedSlot) // Get a parent from the last committed slot. - store, err := i.protocol.MainEngineInstance().Storage.Blocks(lastCommittedSlot) - if err != nil { - return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to get blocks for slot %d", lastCommittedSlot) - } - - expectedErr := ierrors.New("stop iteration") parentBlockID := iotago.EmptyBlockID() - if err = store.StreamKeys(func(blockID iotago.BlockID) error { - parentBlockID = blockID - return expectedErr - }); err != nil && !ierrors.Is(err, expectedErr) { - return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to stream block IDs for slot %d", lastCommittedSlot) + for rootBlock := range i.protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() { + if rootBlock.Slot() > parentBlockID.Slot() { + parentBlockID = rootBlock + } + + // Exit the loop if we found a rootblock in the last committed slot (which is the highest we can get). + if parentBlockID.Slot() == lastCommittedSlot { + break + } } // Get last issued block and start issuing after that subslot. @@ -41,7 +39,7 @@ func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, io } commitUntilSlot := issuingSlot - apiForSlot.ProtocolParameters().MinCommittableAge() - if err = i.protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { + if err := i.protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to force commit until slot %d", commitUntilSlot) } diff --git a/pkg/blockfactory/blockissuer.go b/pkg/blockfactory/blockissuer.go index c3c7f2918..ff96e36c7 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -82,6 +82,7 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, issuerAccount A return nil, ierrors.Wrap(err, "failed to revive chain") } blockParams.BlockHeader.SlotCommitment = commitment + blockParams.BlockHeader.References = make(model.ParentReferences) blockParams.BlockHeader.References[iotago.StrongParentType] = []iotago.BlockID{parentID} } else if err != nil { From 58c91e37db30fffd1ba531888046b3fb8bea5103 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:06:41 +0200 Subject: [PATCH 19/46] Fix error with committee being nil when rolling back engine --- .../sybilprotectionv1/sybilprotection.go | 1 - pkg/storage/prunable/prunable.go | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go b/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go index 8d7b310e0..827e0931c 100644 --- a/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go +++ b/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go @@ -136,7 +136,6 @@ func (o *SybilProtection) CommitSlot(slot iotago.SlotIndex) (committeeRoot, rewa } committee.SetReused() - fmt.Println("reuse committee", currentEpoch, "stake", committee.TotalValidatorStake()) o.seatManager.SetCommittee(nextEpoch, committee) o.events.CommitteeSelected.Trigger(committee, nextEpoch) diff --git a/pkg/storage/prunable/prunable.go b/pkg/storage/prunable/prunable.go index 8ce6e166b..904f13ac7 100644 --- a/pkg/storage/prunable/prunable.go +++ b/pkg/storage/prunable/prunable.go @@ -1,8 +1,6 @@ package prunable import ( - "fmt" - copydir "github.com/otiai10/copy" "github.com/iotaledger/hive.go/ierrors" @@ -163,21 +161,21 @@ func (p *Prunable) Rollback(targetSlot iotago.SlotIndex) error { // Removed entries that belong to the old fork and cannot be re-used. for epoch := lastCommittedEpoch + 1; ; epoch++ { if epoch > targetSlotEpoch { + if deleted := p.prunableSlotStore.DeleteBucket(epoch); !deleted { + break + } + shouldRollback, err := p.shouldRollbackCommittee(epoch, targetSlot) if err != nil { return ierrors.Wrapf(err, "error while checking if committee for epoch %d should be rolled back", epoch) } - fmt.Println("rollback committee", shouldRollback, "epoch", epoch, "lastCommittedEpoch", lastCommittedEpoch, "targetSlotEpoch", targetSlotEpoch) if shouldRollback { if err := p.committee.DeleteEpoch(epoch); err != nil { return ierrors.Wrapf(err, "error while deleting committee for epoch %d", epoch) } } - if deleted := p.prunableSlotStore.DeleteBucket(epoch); !deleted { - break - } } if err := p.poolRewards.DeleteEpoch(epoch); err != nil { From eaafa2301796d56c027c2d9ceab7e46ca23a62a1 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:08:01 +0200 Subject: [PATCH 20/46] Expose AcceptedBlocksCount from notarization manager to detect a "dirty" engine during warp sync --- pkg/protocol/engine/notarization/notarization.go | 2 ++ .../engine/notarization/slotnotarization/manager.go | 4 ++++ .../notarization/slotnotarization/slotmutations.go | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/pkg/protocol/engine/notarization/notarization.go b/pkg/protocol/engine/notarization/notarization.go index 78c3dd88f..e84b75088 100644 --- a/pkg/protocol/engine/notarization/notarization.go +++ b/pkg/protocol/engine/notarization/notarization.go @@ -13,5 +13,7 @@ type Notarization interface { ForceCommit(slot iotago.SlotIndex) (*model.Commitment, error) ForceCommitUntil(commitUntilSlot iotago.SlotIndex) error + AcceptedBlocksCount(index iotago.SlotIndex) int + module.Interface } diff --git a/pkg/protocol/engine/notarization/slotnotarization/manager.go b/pkg/protocol/engine/notarization/slotnotarization/manager.go index ec560d1cb..09f7edcda 100644 --- a/pkg/protocol/engine/notarization/slotnotarization/manager.go +++ b/pkg/protocol/engine/notarization/slotnotarization/manager.go @@ -258,4 +258,8 @@ func (m *Manager) createCommitment(slot iotago.SlotIndex) (*model.Commitment, er return newModelCommitment, nil } +func (m *Manager) AcceptedBlocksCount(index iotago.SlotIndex) int { + return m.slotMutations.AcceptedBlocksCount(index) +} + var _ notarization.Notarization = new(Manager) diff --git a/pkg/protocol/engine/notarization/slotnotarization/slotmutations.go b/pkg/protocol/engine/notarization/slotnotarization/slotmutations.go index 0ea422731..926ec0ae9 100644 --- a/pkg/protocol/engine/notarization/slotnotarization/slotmutations.go +++ b/pkg/protocol/engine/notarization/slotnotarization/slotmutations.go @@ -83,6 +83,15 @@ func (m *SlotMutations) AcceptedBlocks(index iotago.SlotIndex, createIfMissing . return lo.Return1(m.acceptedBlocksBySlot.Get(index)) } +func (m *SlotMutations) AcceptedBlocksCount(index iotago.SlotIndex) int { + acceptedBlocks, exists := m.acceptedBlocksBySlot.Get(index) + if !exists { + return 0 + } + + return acceptedBlocks.Size() +} + // evictUntil removes all data for slots that are older than the given slot. func (m *SlotMutations) evictUntil(index iotago.SlotIndex) { for i := m.latestCommittedIndex + 1; i <= index; i++ { From 141ef3be0ce257aa9274c5031a6ab2e6ca50a997 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:09:32 +0200 Subject: [PATCH 21/46] Reset engine in warp sync when engine is dirty --- pkg/protocol/block_dispatcher.go | 27 ++++++++- pkg/protocol/enginemanager/enginemanager.go | 66 ++++++++++++++++----- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index eae2bd7de..f092cbe1f 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -242,6 +242,31 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment b.processedWarpSyncRequests.Add(commitmentID) + // If the engine is "dirty" we need to restore the state of the engine to the state of the chain commitment. + // As we already decided to switch and sync to this chain we should make sure that processing the blocks from the commitment + // leads to the verified commitment. + if targetEngine.Notarization.AcceptedBlocksCount(commitmentID.Slot()) > 0 { + b.protocol.activeEngineMutex.Lock() + + newEngine, err := b.protocol.EngineManager.RollbackEngine(commitmentID.Slot() - 1) + if err != nil { + return ierrors.Wrapf(err, "failed to rollback engine for slot %d", commitmentID.Slot()) + } + + newEngine.SetChainID(targetEngine.ChainID()) + + if err := b.protocol.EngineManager.SetActiveInstance(newEngine); err != nil { + return ierrors.Wrap(err, "failed to set active engine instance") + } + // + b.protocol.linkToEngine(newEngine) + // + b.protocol.mainEngine.Shutdown() + b.protocol.mainEngine = newEngine + targetEngine = newEngine + b.protocol.activeEngineMutex.Unlock() + } + // Once all blocks are booked we // 1. Mark all transactions as accepted // 2. Mark all blocks as accepted @@ -335,7 +360,7 @@ func (b *BlockDispatcher) inSyncWindow(engine *engine.Engine, block *model.Block // warpSyncIfNecessary triggers a warp sync if necessary. func (b *BlockDispatcher) warpSyncIfNecessary(e *engine.Engine, chainCommitment *chainmanager.ChainCommitment) { - if e == nil { + if e == nil || e.WasShutdown() { return } diff --git a/pkg/protocol/enginemanager/enginemanager.go b/pkg/protocol/enginemanager/enginemanager.go index 01e2efa45..882974aae 100644 --- a/pkg/protocol/enginemanager/enginemanager.go +++ b/pkg/protocol/enginemanager/enginemanager.go @@ -247,10 +247,25 @@ func (e *EngineManager) ForkEngineAtSlot(index iotago.SlotIndex) (*engine.Engine return nil, ierrors.Wrapf(err, "failed to copy storage from active engine instance (%s) to new engine instance (%s)", e.activeInstance.Storage.Directory(), e.directory.Path(engineAlias)) } + if err := e.rollbackStorage(newStorage, index); err != nil { + return nil, ierrors.Wrapf(err, "failed to rollback storage to slot %d", index) + } + + candidateEngine := e.loadEngineInstanceWithStorage(engineAlias, newStorage) + + // Rollback attestations already on created engine instance, because this action modifies the in-memory storage. + if err := candidateEngine.Attestations.Rollback(index); err != nil { + return nil, ierrors.Wrap(err, "error while rolling back attestations storage on candidate engine") + } + + return candidateEngine, nil +} + +func (e *EngineManager) rollbackStorage(newStorage *storage.Storage, slot iotago.SlotIndex) error { // Remove commitments that after forking point. latestCommitment := newStorage.Settings().LatestCommitment() - if err := newStorage.Commitments().Rollback(index, latestCommitment.Slot()); err != nil { - return nil, ierrors.Wrap(err, "failed to rollback commitments") + if err := newStorage.Commitments().Rollback(slot, latestCommitment.Slot()); err != nil { + return ierrors.Wrap(err, "failed to rollback commitments") } // Create temporary components and rollback their permanent state, which will be reflected on disk. evictionState := eviction.NewState(newStorage.LatestNonEmptySlot(), newStorage.RootBlocks) @@ -260,38 +275,57 @@ func (e *EngineManager) ForkEngineAtSlot(index iotago.SlotIndex) (*engine.Engine accountsManager := accountsledger.New(newStorage.Settings().APIProvider(), blockCache.Block, newStorage.AccountDiffs, newStorage.Accounts()) accountsManager.SetLatestCommittedSlot(latestCommitment.Slot()) - if err := accountsManager.Rollback(index); err != nil { - return nil, ierrors.Wrap(err, "failed to rollback accounts manager") + if err := accountsManager.Rollback(slot); err != nil { + return ierrors.Wrap(err, "failed to rollback accounts manager") } - if err := evictionState.Rollback(newStorage.Settings().LatestFinalizedSlot(), index); err != nil { - return nil, ierrors.Wrap(err, "failed to rollback eviction state") + if err := evictionState.Rollback(newStorage.Settings().LatestFinalizedSlot(), slot); err != nil { + return ierrors.Wrap(err, "failed to rollback eviction state") } - if err := newStorage.Ledger().Rollback(index); err != nil { - return nil, err + if err := newStorage.Ledger().Rollback(slot); err != nil { + return err } - targetCommitment, err := newStorage.Commitments().Load(index) + targetCommitment, err := newStorage.Commitments().Load(slot) if err != nil { - return nil, ierrors.Wrapf(err, "error while retrieving commitment for target index %d", index) + return ierrors.Wrapf(err, "error while retrieving commitment for target slot %d", slot) } if err := newStorage.Settings().Rollback(targetCommitment); err != nil { - return nil, err + return err } - if err := newStorage.RollbackPrunable(index); err != nil { - return nil, err + if err := newStorage.RollbackPrunable(slot); err != nil { + return err } - candidateEngine := e.loadEngineInstanceWithStorage(engineAlias, newStorage) + return nil +} + +func (e *EngineManager) RollbackEngine(slot iotago.SlotIndex) (*engine.Engine, error) { + engineAlias := e.activeInstance.Name() + errorHandler := func(err error) { + e.errorHandler(ierrors.Wrapf(err, "engine (%s)", engineAlias[0:8])) + } + + dir := e.activeInstance.Storage.Directory() + e.activeInstance.Shutdown() + + newStorage := storage.Create(dir, e.dbVersion, errorHandler, e.storageOptions...) + + if err := e.rollbackStorage(newStorage, slot); err != nil { + return nil, ierrors.Wrapf(err, "failed to rollback storage to slot %d", slot) + } + + newEngine := e.loadEngineInstanceWithStorage(engineAlias, newStorage) // Rollback attestations already on created engine instance, because this action modifies the in-memory storage. - if err := candidateEngine.Attestations.Rollback(index); err != nil { + if err := newEngine.Attestations.Rollback(slot); err != nil { return nil, ierrors.Wrap(err, "error while rolling back attestations storage on candidate engine") } - return candidateEngine, nil + return newEngine, nil + } func (e *EngineManager) OnEngineCreated(handler func(*engine.Engine)) (unsubscribe func()) { From 4ba848c798127a87257afc9eb0056aea418cf854 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:09:50 +0200 Subject: [PATCH 22/46] Add TestLossOfAcceptanceFromSnapshot --- pkg/tests/loss_of_acceptance_test.go | 73 +++++++++++++++++++++++++++- pkg/testsuite/storage_commitments.go | 31 ++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/pkg/tests/loss_of_acceptance_test.go b/pkg/tests/loss_of_acceptance_test.go index 8235447db..a9e57de37 100644 --- a/pkg/tests/loss_of_acceptance_test.go +++ b/pkg/tests/loss_of_acceptance_test.go @@ -10,6 +10,7 @@ import ( "github.com/iotaledger/iota-core/pkg/blockfactory" "github.com/iotaledger/iota-core/pkg/protocol" "github.com/iotaledger/iota-core/pkg/testsuite" + "github.com/iotaledger/iota-core/pkg/testsuite/mock" iotago "github.com/iotaledger/iota.go/v4" ) @@ -22,6 +23,8 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { testsuite.WithEpochNearingThreshold(2), testsuite.WithSlotsPerEpochExponent(3), testsuite.WithGenesisTimestampOffset(100*10), + + testsuite.WithWaitFor(10*time.Second), ) defer ts.Shutdown() @@ -37,7 +40,6 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { ts.IssueValidationBlock("block0", node0, blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), - blockfactory.WithStrongParents(ts.BlockIDs("Genesis")...), ) require.EqualValues(t, 48, ts.Block("block0").SlotCommitmentID().Slot()) ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0")...) @@ -72,3 +74,72 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { ts.AssertLatestCommitmentSlotIndex(57, ts.Nodes()...) ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("59.0"), true, ts.Nodes()...) } + +func TestLossOfAcceptanceFromSnapshot(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(4), + testsuite.WithEpochNearingThreshold(2), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(100*10), + ) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + ts.AddValidatorNode("node1") + ts.AddNode("node2") + + ts.Run(true, nil) + + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, "Genesis", ts.Nodes(), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(8, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(8, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("10.0"), true, ts.Nodes()...) + + // Create snapshot and restart node0 from it. + var node0restarted *mock.Node + { + snapshotPath := ts.Directory.Path(fmt.Sprintf("%d_snapshot", time.Now().Unix())) + require.NoError(t, ts.Node("node0").Protocol.MainEngineInstance().WriteSnapshot(snapshotPath)) + + node0restarted = ts.AddNode("node0-restarted") + node0restarted.CopyIdentityFromNode(node0) + node0restarted.Initialize(true, + protocol.WithSnapshotPath(snapshotPath), + protocol.WithBaseDirectory(ts.Directory.PathWithCreate(node0restarted.Name)), + ) + ts.Wait() + } + + for _, node := range ts.Nodes("node0", "node1") { + ts.RemoveNode(node.Name) + node.Shutdown() + } + + ts.IssueValidationBlock("block0", node0restarted, + blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), + ) + require.EqualValues(t, 18, ts.Block("block0").SlotCommitmentID().Slot()) + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0-restarted")...) + + // Need to issue to slot 22 so that all other nodes can warp sync up to slot 19 and then commit slot 20 themselves. + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{21, 22}, 2, "block0", ts.Nodes("node0-restarted"), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(20, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(20, ts.Nodes()...) + + // Continue issuing on all nodes for a few slots. + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{23, 24, 25}, 3, "22.1", ts.Nodes(), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(23, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(23, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("25.0"), true, ts.Nodes()...) + + // TODO: check that commitments from 8-19 are empty -> all previously accepted blocks in 9,10 have been orphaned + for _, slot := range []iotago.SlotIndex{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} { + ts.AssertStorageCommitmentBlocks(slot, nil) + } +} diff --git a/pkg/testsuite/storage_commitments.go b/pkg/testsuite/storage_commitments.go index c71f8f006..d5b1a204d 100644 --- a/pkg/testsuite/storage_commitments.go +++ b/pkg/testsuite/storage_commitments.go @@ -57,3 +57,34 @@ func (t *TestSuite) AssertEqualStoredCommitmentAtIndex(index iotago.SlotIndex, n return nil }) } + +func (t *TestSuite) AssertStorageCommitmentBlocks(slot iotago.SlotIndex, expectedBlocks iotago.BlockIDs, nodes ...*mock.Node) { + mustNodes(nodes) + + t.Eventually(func() error { + var commitment *model.Commitment + var commitmentNode *mock.Node + for _, node := range nodes { + storedCommitment, err := node.Protocol.MainEngineInstance().Storage.Commitments().Load(slot) + if err != nil { + return ierrors.Wrapf(err, "AssertStorageCommitmentBlocks: %s: error loading commitment for slot: %d", node.Name, slot) + } + + committedSlot, err := node.Protocol.MainEngineInstance().CommittedSlot(storedCommitment.ID()) + if err != nil { + return ierrors.Wrapf(err, "AssertStorageCommitmentBlocks: %s: error getting committed slot for commitment: %s", node.Name, storedCommitment.ID()) + } + + committedBlocks, err := committedSlot.BlockIDs() + if err != nil { + return ierrors.Wrapf(err, "AssertStorageCommitmentBlocks: %s: error getting committed blocks for slot: %d", node.Name, slot) + } + + if !cmp.Equal(committedBlocks, expectedBlocks) { + return ierrors.Errorf("AssertEqualStoredCommitmentAtIndex: %s: expected %s (from %s), got %s", node.Name, commitment, commitmentNode.Name, storedCommitment) + } + } + + return nil + }) +} From 3f76abda6acb996fd41f848f8a3bfaf21f5efae8 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:47:56 +0200 Subject: [PATCH 23/46] Extend all loss of acceptance tests and add TestLossOfAcceptanceWithRestartFromDisk --- pkg/protocol/events.go | 2 + pkg/tests/loss_of_acceptance_test.go | 193 +++++++++++++++++++++------ pkg/testsuite/mock/node.go | 15 ++- pkg/testsuite/storage_commitments.go | 4 +- pkg/testsuite/testsuite.go | 4 + 5 files changed, 174 insertions(+), 44 deletions(-) diff --git a/pkg/protocol/events.go b/pkg/protocol/events.go index eb50194c1..a39963221 100644 --- a/pkg/protocol/events.go +++ b/pkg/protocol/events.go @@ -10,6 +10,7 @@ import ( type Events struct { CandidateEngineActivated *event.Event1[*engine.Engine] MainEngineSwitched *event.Event1[*engine.Engine] + MainEngineRestarted *event.Event1[*engine.Engine] Error *event.Event1[error] Network *core.Events @@ -23,6 +24,7 @@ var NewEvents = event.CreateGroupConstructor(func() (newEvents *Events) { return &Events{ CandidateEngineActivated: event.New1[*engine.Engine](), MainEngineSwitched: event.New1[*engine.Engine](), + MainEngineRestarted: event.New1[*engine.Engine](), Error: event.New1[error](), Network: core.NewEvents(), diff --git a/pkg/tests/loss_of_acceptance_test.go b/pkg/tests/loss_of_acceptance_test.go index a9e57de37..82e4360f3 100644 --- a/pkg/tests/loss_of_acceptance_test.go +++ b/pkg/tests/loss_of_acceptance_test.go @@ -23,8 +23,6 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { testsuite.WithEpochNearingThreshold(2), testsuite.WithSlotsPerEpochExponent(3), testsuite.WithGenesisTimestampOffset(100*10), - - testsuite.WithWaitFor(10*time.Second), ) defer ts.Shutdown() @@ -38,26 +36,37 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { snapshotPath := ts.Directory.Path(fmt.Sprintf("%d_snapshot", time.Now().Unix())) require.NoError(t, ts.Node("node0").Protocol.MainEngineInstance().WriteSnapshot(snapshotPath)) - ts.IssueValidationBlock("block0", node0, - blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), - ) - require.EqualValues(t, 48, ts.Block("block0").SlotCommitmentID().Slot()) - ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0")...) + // Revive chain on node0. + { + block0 := ts.IssueValidationBlock("block0", node0, + blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), + ) + require.EqualValues(t, 48, ts.Block("block0").SlotCommitmentID().Slot()) + // Reviving the chain should select one parent from the last committed slot. + require.Len(t, block0.Parents(), 1) + require.Equal(t, block0.Parents()[0].Alias(), "Genesis") + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0")...) + } // Need to issue to slot 52 so that all other nodes can warp sync up to slot 49 and then commit slot 50 themselves. - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{51, 52}, 2, "block0", ts.Nodes("node0"), true, nil) + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{51, 52}, 2, "block0", ts.Nodes("node0"), true, nil) - ts.AssertEqualStoredCommitmentAtIndex(50, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(50, ts.Nodes()...) - ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(50, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(50, ts.Nodes()...) + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes()...) + } // Continue issuing on all nodes for a few slots. - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{53, 54, 55, 56, 57}, 3, "52.1", ts.Nodes(), true, nil) + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{53, 54, 55, 56, 57}, 3, "52.1", ts.Nodes(), true, nil) - ts.AssertEqualStoredCommitmentAtIndex(55, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(55, ts.Nodes()...) - ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("57.0"), true, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(55, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(55, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("57.0"), true, ts.Nodes()...) + } + // Start node3 from genesis snapshot. { node3 := ts.AddNode("node3") node3.Initialize(true, @@ -68,11 +77,18 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { } // Continue issuing on all nodes for a few slots. - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{58, 59}, 3, "57.2", ts.Nodes("node0", "node1", "node2"), true, nil) + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{58, 59}, 3, "57.2", ts.Nodes("node0", "node1", "node2"), true, nil) - ts.AssertEqualStoredCommitmentAtIndex(57, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(57, ts.Nodes()...) - ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("59.0"), true, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(57, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(57, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("59.0"), true, ts.Nodes()...) + } + + // Check that commitments from 1-49 are empty. + for slot := iotago.SlotIndex(1); slot <= 49; slot++ { + ts.AssertStorageCommitmentBlocks(slot, nil, ts.Nodes()...) + } } func TestLossOfAcceptanceFromSnapshot(t *testing.T) { @@ -89,15 +105,18 @@ func TestLossOfAcceptanceFromSnapshot(t *testing.T) { node0 := ts.AddValidatorNode("node0") ts.AddValidatorNode("node1") - ts.AddNode("node2") + node2 := ts.AddNode("node2") ts.Run(true, nil) - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, "Genesis", ts.Nodes(), true, nil) + // Issue up to slot 10, committing slot 8. + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, "Genesis", ts.Nodes(), true, nil) - ts.AssertEqualStoredCommitmentAtIndex(8, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(8, ts.Nodes()...) - ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("10.0"), true, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(8, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(8, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("10.0"), true, ts.Nodes()...) + } // Create snapshot and restart node0 from it. var node0restarted *mock.Node @@ -119,27 +138,123 @@ func TestLossOfAcceptanceFromSnapshot(t *testing.T) { node.Shutdown() } - ts.IssueValidationBlock("block0", node0restarted, - blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), + // Revive chain on node0-restarted. + { + block0 := ts.IssueValidationBlock("block0", node0restarted, + blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), + ) + require.EqualValues(t, 18, block0.SlotCommitmentID().Slot()) + // Reviving the chain should select one parent from the last committed slot. + require.Len(t, block0.Parents(), 1) + require.EqualValues(t, block0.Parents()[0].Slot(), 8) + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0-restarted")...) + } + + // Need to issue to slot 22 so that all other nodes can warp sync up to slot 19 and then commit slot 20 themselves. + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{21, 22}, 2, "block0", ts.Nodes("node0-restarted"), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(20, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(20, ts.Nodes()...) + } + + // Continue issuing on all online nodes for a few slots. + { + // Since issued blocks in slot 9 and 10 are be orphaned, we need to make sure that the already issued transactions in the testsuite + // are not used again. + ts.SetAutomaticTransactionIssuingCounters(node2.Partition, 24) + + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{23, 24, 25}, 3, "22.1", ts.Nodes(), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(23, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(23, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("25.0"), true, ts.Nodes()...) + } + + // Check that commitments from 8-19 are empty -> all previously accepted blocks in 9,10 have been orphaned. + for _, slot := range []iotago.SlotIndex{9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} { + ts.AssertStorageCommitmentBlocks(slot, nil, ts.Nodes()...) + } +} + +func TestLossOfAcceptanceWithRestartFromDisk(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(4), + testsuite.WithEpochNearingThreshold(2), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(100*10), ) - require.EqualValues(t, 18, ts.Block("block0").SlotCommitmentID().Slot()) - ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0-restarted")...) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + ts.AddValidatorNode("node1") + node2 := ts.AddNode("node2") + + ts.Run(true, nil) + + // Issue up to slot 10, committing slot 8. + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, "Genesis", ts.Nodes(), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(8, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(8, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("10.0"), true, ts.Nodes()...) + } + + for _, node := range ts.Nodes("node0", "node1") { + ts.RemoveNode(node.Name) + node.Shutdown() + } + + // Create snapshot and restart node0 from it. + var node0restarted *mock.Node + { + node0restarted = ts.AddNode("node0-restarted") + node0restarted.CopyIdentityFromNode(node0) + node0restarted.Initialize(true, + protocol.WithBaseDirectory(ts.Directory.PathWithCreate(node0.Name)), + ) + ts.Wait() + } + + // Revive chain on node0-restarted. + { + block0 := ts.IssueValidationBlock("block0", node0restarted, + blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), + ) + require.EqualValues(t, 18, block0.SlotCommitmentID().Slot()) + // Reviving the chain should select one parent from the last committed slot. + require.Len(t, block0.Parents(), 1) + require.EqualValues(t, block0.Parents()[0].Slot(), 8) + ts.AssertBlocksExist(ts.Blocks("block0"), true, ts.Nodes("node0-restarted")...) + } // Need to issue to slot 22 so that all other nodes can warp sync up to slot 19 and then commit slot 20 themselves. - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{21, 22}, 2, "block0", ts.Nodes("node0-restarted"), true, nil) + { + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{21, 22}, 2, "block0", ts.Nodes("node0-restarted"), true, nil) - ts.AssertEqualStoredCommitmentAtIndex(20, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(20, ts.Nodes()...) + ts.AssertEqualStoredCommitmentAtIndex(20, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(20, ts.Nodes()...) + } - // Continue issuing on all nodes for a few slots. - ts.IssueBlocksAtSlots("", []iotago.SlotIndex{23, 24, 25}, 3, "22.1", ts.Nodes(), true, nil) + // Continue issuing on all online nodes for a few slots. + { + // Since issued blocks in slot 9 and 10 are be orphaned, we need to make sure that the already issued transactions in the testsuite + // are not used again. + ts.SetAutomaticTransactionIssuingCounters(node2.Partition, 24) - ts.AssertEqualStoredCommitmentAtIndex(23, ts.Nodes()...) - ts.AssertLatestCommitmentSlotIndex(23, ts.Nodes()...) - ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("25.0"), true, ts.Nodes()...) + ts.IssueBlocksAtSlots("", []iotago.SlotIndex{23, 24, 25}, 3, "22.1", ts.Nodes(), true, nil) + + ts.AssertEqualStoredCommitmentAtIndex(23, ts.Nodes()...) + ts.AssertLatestCommitmentSlotIndex(23, ts.Nodes()...) + ts.AssertBlocksInCacheAccepted(ts.BlocksWithPrefix("25.0"), true, ts.Nodes()...) + } - // TODO: check that commitments from 8-19 are empty -> all previously accepted blocks in 9,10 have been orphaned - for _, slot := range []iotago.SlotIndex{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} { - ts.AssertStorageCommitmentBlocks(slot, nil) + // Check that commitments from 8-19 are empty -> all previously accepted blocks in 9,10 have been orphaned. + for _, slot := range []iotago.SlotIndex{9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} { + ts.AssertStorageCommitmentBlocks(slot, nil, ts.Nodes()...) } } diff --git a/pkg/testsuite/mock/node.go b/pkg/testsuite/mock/node.go index 5ffe01254..cccd16ae8 100644 --- a/pkg/testsuite/mock/node.go +++ b/pkg/testsuite/mock/node.go @@ -210,6 +210,12 @@ func (n *Node) hookLogging(failOnBlockFiltered bool) { fmt.Printf("%s > MainEngineSwitched: %s, ChainID:%s Slot:%s\n", n.Name, e.Name(), e.ChainID(), e.ChainID().Slot()) }) + events.MainEngineRestarted.Hook(func(e *engine.Engine) { + fmt.Printf("%s > MainEngineRestarted: %s, ChainID:%s Slot:%s\n", n.Name, e.Name(), e.ChainID(), e.ChainID().Slot()) + + n.attachEngineLogsWithName(failOnBlockFiltered, e, fmt.Sprintf("Main2 - %s", e.Name()[:8])) + }) + events.Network.Error.Hook(func(err error, id peer.ID) { fmt.Printf("%s > Network.Error: from %s %s\n", n.Name, id, err) }) @@ -219,8 +225,7 @@ func (n *Node) hookLogging(failOnBlockFiltered bool) { }) } -func (n *Node) attachEngineLogs(failOnBlockFiltered bool, instance *engine.Engine) { - engineName := fmt.Sprintf("%s - %s", lo.Cond(n.Protocol.MainEngineInstance() != instance, "Candidate", "Main"), instance.Name()[:8]) +func (n *Node) attachEngineLogsWithName(failOnBlockFiltered bool, instance *engine.Engine, engineName string) { events := instance.Events events.BlockDAG.BlockAttached.Hook(func(block *blocks.Block) { @@ -435,6 +440,12 @@ func (n *Node) attachEngineLogs(failOnBlockFiltered bool, instance *engine.Engin }) } +func (n *Node) attachEngineLogs(failOnBlockFiltered bool, instance *engine.Engine) { + engineName := fmt.Sprintf("%s - %s", lo.Cond(n.Protocol.MainEngineInstance() != instance, "Candidate", "Main"), instance.Name()[:8]) + + n.attachEngineLogsWithName(failOnBlockFiltered, instance, engineName) +} + func (n *Node) Wait() { n.Workers.WaitChildren() } diff --git a/pkg/testsuite/storage_commitments.go b/pkg/testsuite/storage_commitments.go index d5b1a204d..b8c8e22f4 100644 --- a/pkg/testsuite/storage_commitments.go +++ b/pkg/testsuite/storage_commitments.go @@ -62,8 +62,6 @@ func (t *TestSuite) AssertStorageCommitmentBlocks(slot iotago.SlotIndex, expecte mustNodes(nodes) t.Eventually(func() error { - var commitment *model.Commitment - var commitmentNode *mock.Node for _, node := range nodes { storedCommitment, err := node.Protocol.MainEngineInstance().Storage.Commitments().Load(slot) if err != nil { @@ -81,7 +79,7 @@ func (t *TestSuite) AssertStorageCommitmentBlocks(slot iotago.SlotIndex, expecte } if !cmp.Equal(committedBlocks, expectedBlocks) { - return ierrors.Errorf("AssertEqualStoredCommitmentAtIndex: %s: expected %s (from %s), got %s", node.Name, commitment, commitmentNode.Name, storedCommitment) + return ierrors.Errorf("AssertStorageCommitmentBlocks: %s: expected %s, got %s", node.Name, expectedBlocks, committedBlocks) } } diff --git a/pkg/testsuite/testsuite.go b/pkg/testsuite/testsuite.go index c9a29042c..1b9d8a69f 100644 --- a/pkg/testsuite/testsuite.go +++ b/pkg/testsuite/testsuite.go @@ -511,3 +511,7 @@ func (t *TestSuite) SplitIntoPartitions(partitions map[string][]*mock.Node) { func (t *TestSuite) MergePartitionsToMain(partitions ...string) { t.network.MergePartitionsToMain(partitions...) } + +func (t *TestSuite) SetAutomaticTransactionIssuingCounters(partition string, newValue int) { + t.automaticTransactionIssuingCounters.Set(partition, newValue) +} From 8f133de7215f4be79b17f82e4fb19b26ebf98ebc Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:29:54 +0200 Subject: [PATCH 24/46] When starting up node ensure that a consistent state is created by deleting all data in not yet committed slots from storage. Also delete shortcutting of block requests for already accepted blocks after startup --- pkg/protocol/block_dispatcher.go | 1 + pkg/protocol/engine/engine.go | 30 ++------------------- pkg/protocol/enginemanager/enginemanager.go | 18 ++++++++++--- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index f092cbe1f..0d5a6dd2a 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -252,6 +252,7 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment if err != nil { return ierrors.Wrapf(err, "failed to rollback engine for slot %d", commitmentID.Slot()) } + b.protocol.Events.MainEngineRestarted.Trigger(newEngine) newEngine.SetChainID(targetEngine.ChainID()) diff --git a/pkg/protocol/engine/engine.go b/pkg/protocol/engine/engine.go index a5e0087c3..feb75c004 100644 --- a/pkg/protocol/engine/engine.go +++ b/pkg/protocol/engine/engine.go @@ -71,9 +71,8 @@ type Engine struct { BlockCache *blocks.Blocks - startupAvailableBlocksWindow iotago.SlotIndex - chainID iotago.CommitmentID - mutex syncutils.RWMutex + chainID iotago.CommitmentID + mutex syncutils.RWMutex optsSnapshotPath string optsEntryPointsDepth int @@ -207,10 +206,6 @@ func New( if err := e.UpgradeOrchestrator.RestoreFromDisk(e.Storage.Settings().LatestCommitment().Slot()); err != nil { panic(ierrors.Wrap(err, "failed to restore upgrade orchestrator from disk")) } - - // When we start from disk we potentially have previously accepted blocks in window (latestCommitment, latestCommitment + maxCommittableAge] - // on disk. We store this information that we can load blocks instead of requesting them again. - e.startupAvailableBlocksWindow = e.Storage.Settings().LatestCommitment().Slot() + e.CurrentAPI().ProtocolParameters().MaxCommittableAge() } }, func(e *Engine) { @@ -261,11 +256,6 @@ func (e *Engine) Block(id iotago.BlockID) (*model.Block, bool) { return cachedBlock.ModelBlock(), !cachedBlock.IsMissing() } - // The block should've been in the block cache, so there's no need to check the storage. - if !exists && id.Slot() > e.startupAvailableBlocksWindow && id.Slot() > e.Storage.Settings().LatestCommitment().Slot() { - return nil, false - } - s, err := e.Storage.Blocks(id.Slot()) if err != nil { e.errorHandler(ierrors.Wrap(err, "failed to get block storage")) @@ -465,25 +455,9 @@ func (e *Engine) setupBlockRequester() { e.Events.EvictionState.SlotEvicted.Hook(e.BlockRequester.EvictUntil) - wp := e.Workers.CreatePool("BlockMissingAttachFromStorage", 1) // We need to hook to make sure that the request is created before the block arrives to avoid a race condition // where we try to delete the request again before it is created. Thus, continuing to request forever. e.Events.BlockDAG.BlockMissing.Hook(func(block *blocks.Block) { - if block.ID().Slot() < e.startupAvailableBlocksWindow { - // We shortcut requesting blocks that are in the storage in case we did shut down and restart. - // We can safely ignore all errors. - if blockStorage, err := e.Storage.Blocks(block.ID().Slot()); err == nil { - if storedBlock, _ := blockStorage.Load(block.ID()); storedBlock != nil { - // We need to attach the block to the DAG in a separate worker pool to avoid a deadlock with the block cache - // as the BlockMissing event is triggered within a GetOrCreate call. - wp.Submit(func() { - _, _, _ = e.BlockDAG.Attach(storedBlock) - }) - - return - } - } - } e.BlockRequester.StartTicker(block.ID()) }) e.Events.BlockDAG.MissingBlockAttached.Hook(func(block *blocks.Block) { diff --git a/pkg/protocol/enginemanager/enginemanager.go b/pkg/protocol/enginemanager/enginemanager.go index 882974aae..a36b01175 100644 --- a/pkg/protocol/enginemanager/enginemanager.go +++ b/pkg/protocol/enginemanager/enginemanager.go @@ -139,6 +139,18 @@ func (e *EngineManager) LoadActiveEngine(snapshotPath string) (*engine.Engine, e if exists, isDirectory, err := ioutils.PathExists(e.directory.Path(info.Name)); err == nil && exists && isDirectory { // Load previous engine as active e.activeInstance = e.loadEngineInstanceFromSnapshot(info.Name, snapshotPath) + + // Clear the storage of the active instance to be consistent with the latest committed slot. + // Everything after the latest committed slot is pruned to ensure a consistent state (e.g. accepted blocks). + targetSlot := e.activeInstance.Storage.Settings().LatestCommitment().Slot() + if err := e.rollbackStorage(e.activeInstance.Storage, targetSlot); err != nil { + return nil, ierrors.Wrapf(err, "failed to rollback storage to slot %d", targetSlot) + } + + // Rollback attestations already on created engine instance, because this action modifies the in-memory storage. + if err := e.activeInstance.Attestations.Rollback(targetSlot); err != nil { + return nil, ierrors.Wrap(err, "error while rolling back attestations storage on candidate engine") + } } } @@ -283,7 +295,7 @@ func (e *EngineManager) rollbackStorage(newStorage *storage.Storage, slot iotago return ierrors.Wrap(err, "failed to rollback eviction state") } if err := newStorage.Ledger().Rollback(slot); err != nil { - return err + return ierrors.Wrapf(err, "failed to rollback ledger to slot %d", slot) } targetCommitment, err := newStorage.Commitments().Load(slot) @@ -292,11 +304,11 @@ func (e *EngineManager) rollbackStorage(newStorage *storage.Storage, slot iotago } if err := newStorage.Settings().Rollback(targetCommitment); err != nil { - return err + return ierrors.Wrap(err, "failed to rollback settings") } if err := newStorage.RollbackPrunable(slot); err != nil { - return err + return ierrors.Wrap(err, "failed to rollback prunable data") } return nil From ffe86cf57a26fad1c9b714f44ebf171dddd23100 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 3 Oct 2023 12:05:13 +0200 Subject: [PATCH 25/46] Fix tests and update go.mod to latest iota.go --- go.mod | 2 +- go.sum | 4 ++-- pkg/blockfactory/acceptance_loss.go | 6 ------ pkg/storage/prunable/prunable.go | 11 +++++++---- pkg/tests/protocol_engine_rollback_test.go | 2 +- pkg/tests/protocol_startup_test.go | 3 +-- tools/evil-spammer/go.mod | 2 +- tools/evil-spammer/go.sum | 4 ++-- tools/gendoc/go.mod | 2 +- tools/gendoc/go.sum | 4 ++-- tools/genesis-snapshot/go.mod | 2 +- tools/genesis-snapshot/go.sum | 4 ++-- 12 files changed, 21 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 760bdc365..c6e3e2767 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182 github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230927140257-bfa0bb0af2bd - github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf + github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 github.com/labstack/echo/v4 v4.11.1 github.com/labstack/gommon v0.4.0 github.com/libp2p/go-libp2p v0.30.0 diff --git a/go.sum b/go.sum index 61beb8884..66653be05 100644 --- a/go.sum +++ b/go.sum @@ -305,8 +305,8 @@ github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182 h1:lQikt github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182/go.mod h1:q24QEsS887ZWJVX76w2kwSgC84KS7wIKOy1otuqZ2ZM= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230927140257-bfa0bb0af2bd h1:nFG3Zq/zFA4KhBYFX2IezX1C74zfE0DqCt0LrgTa9Ig= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230927140257-bfa0bb0af2bd/go.mod h1:c5778OnWpLq108YE+Eb2m8Ri/t/4ydV0TvI/Sy5YivQ= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf h1:TNt6qra1H62HctwYhoxujPml/uN2AtnE1zMkB5kkVfI= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 h1:ckMsGF5YQ2FXIGSZuIEIbNTKkzUCw+eQQVfgwDRt0P0= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY= github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/pkg/blockfactory/acceptance_loss.go b/pkg/blockfactory/acceptance_loss.go index 188847211..3014a42e8 100644 --- a/pkg/blockfactory/acceptance_loss.go +++ b/pkg/blockfactory/acceptance_loss.go @@ -24,12 +24,6 @@ func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, io } } - // Get last issued block and start issuing after that subslot. - // TODO: also make sure to not issue on two distinct chains within the same slot. - lastIssuedBlockValidationBlock := i.protocol.MainEngineInstance().Storage.Settings().LatestIssuedValidationBlock() - if lastIssuedBlockValidationBlock != nil { - - } issuingSlot := apiForSlot.TimeProvider().SlotFromTime(issuingTime) // Force commitments until minCommittableAge relative to the block's issuing time. We basically "pretend" that diff --git a/pkg/storage/prunable/prunable.go b/pkg/storage/prunable/prunable.go index 904f13ac7..1fc392877 100644 --- a/pkg/storage/prunable/prunable.go +++ b/pkg/storage/prunable/prunable.go @@ -161,10 +161,6 @@ func (p *Prunable) Rollback(targetSlot iotago.SlotIndex) error { // Removed entries that belong to the old fork and cannot be re-used. for epoch := lastCommittedEpoch + 1; ; epoch++ { if epoch > targetSlotEpoch { - if deleted := p.prunableSlotStore.DeleteBucket(epoch); !deleted { - break - } - shouldRollback, err := p.shouldRollbackCommittee(epoch, targetSlot) if err != nil { return ierrors.Wrapf(err, "error while checking if committee for epoch %d should be rolled back", epoch) @@ -176,6 +172,9 @@ func (p *Prunable) Rollback(targetSlot iotago.SlotIndex) error { } } + if deleted := p.prunableSlotStore.DeleteBucket(epoch); !deleted { + break + } } if err := p.poolRewards.DeleteEpoch(epoch); err != nil { @@ -207,6 +206,10 @@ func (p *Prunable) shouldRollbackCommittee(epoch iotago.EpochIndex, targetSlot i return false, err } + if committee == nil { + return false, nil + } + return committee.IsReused(), nil } diff --git a/pkg/tests/protocol_engine_rollback_test.go b/pkg/tests/protocol_engine_rollback_test.go index 79381bf1f..c92234afd 100644 --- a/pkg/tests/protocol_engine_rollback_test.go +++ b/pkg/tests/protocol_engine_rollback_test.go @@ -762,7 +762,7 @@ func TestProtocol_EngineRollbackNoFinalizationBeforePointOfNoReturn(t *testing.T require.Len(t, committeeEpoch.IDs(), 4) } - // Commmittee for the future epoch does not exist. + // Committee for the future epoch does not exist. committeeEpoch2, err := newEngine.Storage.Committee().Load(2) require.NoError(t, err) require.Nil(t, committeeEpoch2) diff --git a/pkg/tests/protocol_startup_test.go b/pkg/tests/protocol_startup_test.go index 03af7cc9b..83e36e249 100644 --- a/pkg/tests/protocol_startup_test.go +++ b/pkg/tests/protocol_startup_test.go @@ -201,8 +201,7 @@ func Test_StartNodeFromSnapshotAndDisk(t *testing.T) { ) ts.Wait() - // Everything that was accepted before shutting down should be available on disk (verifying that restoring the block cache from disk works). - ts.AssertBlocksExist(ts.BlocksWithPrefixes("8", "9", "11", "12", "13.0", "13.1", "13.2", "13.3"), true, ts.Nodes("nodeC-restarted")...) + // Everything that was accepted before shutting down should be available on disk. ts.AssertStorageRootBlocks(expectedStorageRootBlocksFrom0, ts.Nodes("nodeC-restarted")...) for _, slot := range []iotago.SlotIndex{8, 9, 11} { diff --git a/tools/evil-spammer/go.mod b/tools/evil-spammer/go.mod index fe5c76608..95e1eb5de 100644 --- a/tools/evil-spammer/go.mod +++ b/tools/evil-spammer/go.mod @@ -17,7 +17,7 @@ require ( github.com/iotaledger/hive.go/runtime v0.0.0-20230929122509-67f34bfed40d github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota-core/tools/genesis-snapshot v0.0.0-00010101000000-000000000000 - github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf + github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 github.com/mr-tron/base58 v1.2.0 go.uber.org/atomic v1.11.0 ) diff --git a/tools/evil-spammer/go.sum b/tools/evil-spammer/go.sum index db415376d..7909f1956 100644 --- a/tools/evil-spammer/go.sum +++ b/tools/evil-spammer/go.sum @@ -195,8 +195,8 @@ github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bf github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bfed40d/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d h1:ekHWRypoaiCXgrJVUQS7rCewsK3FuG1gTbPxu5jYn9c= github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf h1:TNt6qra1H62HctwYhoxujPml/uN2AtnE1zMkB5kkVfI= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 h1:ckMsGF5YQ2FXIGSZuIEIbNTKkzUCw+eQQVfgwDRt0P0= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= diff --git a/tools/gendoc/go.mod b/tools/gendoc/go.mod index aa7509b57..60cd68550 100644 --- a/tools/gendoc/go.mod +++ b/tools/gendoc/go.mod @@ -72,7 +72,7 @@ require ( github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d // indirect github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182 // indirect github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230927140257-bfa0bb0af2bd // indirect - github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf // indirect + github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 // indirect github.com/ipfs/boxo v0.10.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-datastore v0.6.0 // indirect diff --git a/tools/gendoc/go.sum b/tools/gendoc/go.sum index d76e197ee..6212f3ca6 100644 --- a/tools/gendoc/go.sum +++ b/tools/gendoc/go.sum @@ -311,8 +311,8 @@ github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182 h1:lQikt github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182/go.mod h1:q24QEsS887ZWJVX76w2kwSgC84KS7wIKOy1otuqZ2ZM= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230927140257-bfa0bb0af2bd h1:nFG3Zq/zFA4KhBYFX2IezX1C74zfE0DqCt0LrgTa9Ig= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230927140257-bfa0bb0af2bd/go.mod h1:c5778OnWpLq108YE+Eb2m8Ri/t/4ydV0TvI/Sy5YivQ= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf h1:TNt6qra1H62HctwYhoxujPml/uN2AtnE1zMkB5kkVfI= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 h1:ckMsGF5YQ2FXIGSZuIEIbNTKkzUCw+eQQVfgwDRt0P0= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY= github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/tools/genesis-snapshot/go.mod b/tools/genesis-snapshot/go.mod index 940a8ff26..1b5676d76 100644 --- a/tools/genesis-snapshot/go.mod +++ b/tools/genesis-snapshot/go.mod @@ -10,7 +10,7 @@ require ( github.com/iotaledger/hive.go/lo v0.0.0-20230929122509-67f34bfed40d github.com/iotaledger/hive.go/runtime v0.0.0-20230929122509-67f34bfed40d github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 - github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf + github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 github.com/mr-tron/base58 v1.2.0 github.com/spf13/pflag v1.0.5 golang.org/x/crypto v0.13.0 diff --git a/tools/genesis-snapshot/go.sum b/tools/genesis-snapshot/go.sum index bfe88c8e9..e1668f37b 100644 --- a/tools/genesis-snapshot/go.sum +++ b/tools/genesis-snapshot/go.sum @@ -50,8 +50,8 @@ github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bf github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bfed40d/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d h1:ekHWRypoaiCXgrJVUQS7rCewsK3FuG1gTbPxu5jYn9c= github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf h1:TNt6qra1H62HctwYhoxujPml/uN2AtnE1zMkB5kkVfI= -github.com/iotaledger/iota.go/v4 v4.0.0-20231002120511-9ab88bf44daf/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6 h1:ckMsGF5YQ2FXIGSZuIEIbNTKkzUCw+eQQVfgwDRt0P0= +github.com/iotaledger/iota.go/v4 v4.0.0-20231003100138-f5896e9f94f6/go.mod h1:+e3bsJFDr9HxmUMe+eQOLNut5wfcB/ivhJdouOJgOnE= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= From b8a8a056d5e7ce2c44aa6dde8b85248ef95d4a38 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:17:46 +0200 Subject: [PATCH 26/46] Fixes after merge --- pkg/protocol/block_dispatcher.go | 2 +- pkg/protocol/engine/committed_slot_api.go | 2 +- pkg/protocol/engine/mempool/v1/mempool.go | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 0d5a6dd2a..4249f0245 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -229,7 +229,7 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment return ierrors.Errorf("failed to verify tangle merkle proof for %s", commitmentID) } - acceptedTransactionIDs := ads.NewSet[iotago.BlockID](mapdb.NewMapDB(), iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes) + acceptedTransactionIDs := ads.NewSet[iotago.TransactionID](mapdb.NewMapDB(), iotago.TransactionID.Bytes, iotago.TransactionIDFromBytes) for _, transactionID := range transactionIDs { _ = acceptedTransactionIDs.Add(transactionID) // a mapdb can never return an error } diff --git a/pkg/protocol/engine/committed_slot_api.go b/pkg/protocol/engine/committed_slot_api.go index 579f27a55..faaace0dc 100644 --- a/pkg/protocol/engine/committed_slot_api.go +++ b/pkg/protocol/engine/committed_slot_api.go @@ -83,7 +83,7 @@ func (c *CommittedSlotAPI) TransactionIDs() (iotago.TransactionIDs, error) { return nil, ierrors.Errorf("failed to get mutations of slot index %d", c.CommitmentID.Slot()) } - set := ads.NewSet(store, iotago.TransactionID.Bytes, iotago.SlotIdentifierFromBytes) + set := ads.NewSet(store, iotago.TransactionID.Bytes, iotago.TransactionIDFromBytes) transactionIDs := make(iotago.TransactionIDs, 0, set.Size()) if err = set.Stream(func(key iotago.TransactionID) error { diff --git a/pkg/protocol/engine/mempool/v1/mempool.go b/pkg/protocol/engine/mempool/v1/mempool.go index 5e5d58409..14e18c0c0 100644 --- a/pkg/protocol/engine/mempool/v1/mempool.go +++ b/pkg/protocol/engine/mempool/v1/mempool.go @@ -70,6 +70,7 @@ type MemPool[VoteRank conflictdag.VoteRankType[VoteRank]] struct { func New[VoteRank conflictdag.VoteRankType[VoteRank]]( vm mempool.VM, stateResolver mempool.StateResolver, + mutationsFunc func(iotago.SlotIndex) (kvstore.KVStore, error), workers *workerpool.Group, conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, mempool.StateID, VoteRank], errorHandler func(error), @@ -78,6 +79,7 @@ func New[VoteRank conflictdag.VoteRankType[VoteRank]]( return options.Apply(&MemPool[VoteRank]{ vm: vm, resolveState: stateResolver, + mutationsFunc: mutationsFunc, attachments: memstorage.NewIndexedStorage[iotago.SlotIndex, iotago.BlockID, *SignedTransactionMetadata](), cachedTransactions: shrinkingmap.New[iotago.TransactionID, *TransactionMetadata](), cachedSignedTransactions: shrinkingmap.New[iotago.SignedTransactionID, *SignedTransactionMetadata](), @@ -402,11 +404,15 @@ func (m *MemPool[VoteRank]) stateDiff(slot iotago.SlotIndex) (*StateDiff, error) func (m *MemPool[VoteRank]) setupTransaction(transaction *TransactionMetadata) { transaction.OnAccepted(func() { + // Transactions can only become accepted if there is at least one attachment is included. if slot := transaction.EarliestIncludedAttachment().Slot(); slot != 0 { - if stateDiff, evicted := m.stateDiff(slot); !evicted { - if err := stateDiff.AddTransaction(transaction, m.errorHandler); err != nil { - m.errorHandler(ierrors.Wrapf(err, "failed to add transaction to state diff, txID: %s", transaction.ID())) - } + stateDiff, err := m.stateDiff(slot) + if err != nil { + m.errorHandler(ierrors.Wrapf(err, "failed to get state diff for slot %d", slot)) + } + + if err := stateDiff.AddTransaction(transaction, m.errorHandler); err != nil { + m.errorHandler(ierrors.Wrapf(err, "failed to add transaction to state diff, txID: %s", transaction.ID())) } } }) From 8d5b08255647d4be84e3e162a2d245c63b09974e Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:03:28 +0900 Subject: [PATCH 27/46] Address review comments --- pkg/blockfactory/acceptance_loss.go | 4 ++-- pkg/blockfactory/blockissuer.go | 6 ++--- pkg/protocol/block_dispatcher.go | 7 +++--- pkg/protocol/engine/committed_slot_api.go | 4 ++-- pkg/protocol/engine/mempool/v1/mempool.go | 28 +++++++++-------------- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/pkg/blockfactory/acceptance_loss.go b/pkg/blockfactory/acceptance_loss.go index 3014a42e8..076a5b53c 100644 --- a/pkg/blockfactory/acceptance_loss.go +++ b/pkg/blockfactory/acceptance_loss.go @@ -11,7 +11,7 @@ func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, io lastCommittedSlot := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() apiForSlot := i.protocol.APIForSlot(lastCommittedSlot) - // Get a parent from the last committed slot. + // Get a rootblock as recent as possible for the parent. parentBlockID := iotago.EmptyBlockID() for rootBlock := range i.protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() { if rootBlock.Slot() > parentBlockID.Slot() { @@ -39,7 +39,7 @@ func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, io commitment, err := i.protocol.MainEngineInstance().Storage.Commitments().Load(commitUntilSlot) if err != nil { - return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to load commitment for slot %d", commitUntilSlot) + return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to commit until slot %d to revive chain", commitUntilSlot) } return commitment.Commitment(), parentBlockID, nil diff --git a/pkg/blockfactory/blockissuer.go b/pkg/blockfactory/blockissuer.go index 3717d607a..2abbbe62f 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -75,7 +75,7 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, issuerAccount A if blockParams.BlockHeader.SlotCommitment == nil { var err error - blockParams.BlockHeader.SlotCommitment, err = i.getCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) + blockParams.BlockHeader.SlotCommitment, err = i.getAddressableCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) if err != nil && ierrors.Is(err, ErrBlockTooRecent) { commitment, parentID, err := i.reviveChain(*blockParams.BlockHeader.IssuingTime) if err != nil { @@ -182,7 +182,7 @@ func (i *BlockIssuer) CreateBlock(ctx context.Context, issuerAccount Account, op if blockParams.BlockHeader.SlotCommitment == nil { var err error - blockParams.BlockHeader.SlotCommitment, err = i.getCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) + blockParams.BlockHeader.SlotCommitment, err = i.getAddressableCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) if err != nil { return nil, ierrors.Wrap(err, "error getting commitment") } @@ -440,7 +440,7 @@ func (i *BlockIssuer) setDefaultBlockParams(blockParams *BlockHeaderParams, issu return nil } -func (i *BlockIssuer) getCommitment(blockSlot iotago.SlotIndex) (*iotago.Commitment, error) { +func (i *BlockIssuer) getAddressableCommitment(blockSlot iotago.SlotIndex) (*iotago.Commitment, error) { protoParams := i.protocol.CurrentAPI().ProtocolParameters() commitment := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment() diff --git a/pkg/protocol/block_dispatcher.go b/pkg/protocol/block_dispatcher.go index 4249f0245..9695fcd72 100644 --- a/pkg/protocol/block_dispatcher.go +++ b/pkg/protocol/block_dispatcher.go @@ -214,7 +214,7 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment return ierrors.Errorf("failed to get target engine for %s", commitmentID) } - // Make sure that already evicted commitments are not processed. This might happen if there's a lot of slots to process ] + // Make sure that already evicted commitments are not processed. This might happen if there's a lot of slots to process // and old responses are still in the task queue. if loadedCommitment, err := targetEngine.Storage.Commitments().Load(commitmentID.Slot()); err == nil && loadedCommitment.ID() == commitmentID { return nil @@ -259,9 +259,9 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment if err := b.protocol.EngineManager.SetActiveInstance(newEngine); err != nil { return ierrors.Wrap(err, "failed to set active engine instance") } - // + b.protocol.linkToEngine(newEngine) - // + b.protocol.mainEngine.Shutdown() b.protocol.mainEngine = newEngine targetEngine = newEngine @@ -329,6 +329,7 @@ func (b *BlockDispatcher) processWarpSyncResponse(commitmentID iotago.Commitment for _, blockID := range blockIDs { block, _ := targetEngine.BlockDAG.GetOrRequestBlock(blockID) if block == nil { // this should never happen as we're requesting the blocks for this slot so it can't be evicted. + b.protocol.HandleError(ierrors.Errorf("failed to get block %s", blockID)) continue } diff --git a/pkg/protocol/engine/committed_slot_api.go b/pkg/protocol/engine/committed_slot_api.go index faaace0dc..62d02a279 100644 --- a/pkg/protocol/engine/committed_slot_api.go +++ b/pkg/protocol/engine/committed_slot_api.go @@ -86,8 +86,8 @@ func (c *CommittedSlotAPI) TransactionIDs() (iotago.TransactionIDs, error) { set := ads.NewSet(store, iotago.TransactionID.Bytes, iotago.TransactionIDFromBytes) transactionIDs := make(iotago.TransactionIDs, 0, set.Size()) - if err = set.Stream(func(key iotago.TransactionID) error { - transactionIDs = append(transactionIDs, key) + if err = set.Stream(func(txID iotago.TransactionID) error { + transactionIDs = append(transactionIDs, txID) return nil }); err != nil { return nil, ierrors.Wrapf(err, "failed to iterate over mutations of slot %d", c.CommitmentID.Slot()) diff --git a/pkg/protocol/engine/mempool/v1/mempool.go b/pkg/protocol/engine/mempool/v1/mempool.go index b508a6f32..e675aa47c 100644 --- a/pkg/protocol/engine/mempool/v1/mempool.go +++ b/pkg/protocol/engine/mempool/v1/mempool.go @@ -178,8 +178,15 @@ func (m *MemPool[VoteRank]) TransactionMetadataByAttachment(blockID iotago.Block // StateDiff returns the state diff for the given slot. func (m *MemPool[VoteRank]) StateDiff(slot iotago.SlotIndex) (mempool.StateDiff, error) { - if stateDiff, exists := m.stateDiffs.Get(slot); exists { - return stateDiff, nil + m.evictionMutex.RLock() + defer m.evictionMutex.RUnlock() + + return m.stateDiff(slot) +} + +func (m *MemPool[VoteRank]) stateDiff(slot iotago.SlotIndex) (*StateDiff, error) { + if m.lastEvictedSlot >= slot { + return nil, ierrors.Errorf("slot %d is older than last evicted slot %d", slot, m.lastEvictedSlot) } kv, err := m.mutationsFunc(slot) @@ -187,7 +194,7 @@ func (m *MemPool[VoteRank]) StateDiff(slot iotago.SlotIndex) (mempool.StateDiff, return nil, ierrors.Wrapf(err, "failed to get state diff for slot %d", slot) } - return NewStateDiff(slot, kv), nil + return lo.Return1(m.stateDiffs.GetOrCreate(slot, func() *StateDiff { return NewStateDiff(slot, kv) })), nil } // Evict evicts the slot with the given slot from the MemPool. @@ -438,22 +445,9 @@ func (m *MemPool[VoteRank]) setup() { }) } -func (m *MemPool[VoteRank]) stateDiff(slot iotago.SlotIndex) (*StateDiff, error) { - if m.lastEvictedSlot >= slot { - return nil, ierrors.Errorf("slot %d is older than last evicted slot %d", slot, m.lastEvictedSlot) - } - - kv, err := m.mutationsFunc(slot) - if err != nil { - return nil, ierrors.Wrapf(err, "failed to get state diff for slot %d", slot) - } - - return lo.Return1(m.stateDiffs.GetOrCreate(slot, func() *StateDiff { return NewStateDiff(slot, kv) })), nil -} - func (m *MemPool[VoteRank]) setupTransaction(transaction *TransactionMetadata) { transaction.OnAccepted(func() { - // Transactions can only become accepted if there is at least one attachment is included. + // Transactions can only become accepted if there is at least one attachment included. if slot := transaction.EarliestIncludedAttachment().Slot(); slot != 0 { stateDiff, err := m.stateDiff(slot) if err != nil { From 6fa21b685bad13430eaf2174978495d585ecd51d Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 12:19:08 +0200 Subject: [PATCH 28/46] Do not pass latest commitment to CreateValidationBlock nullifying chain revive --- components/validator/issuer.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/validator/issuer.go b/components/validator/issuer.go index 6ea188566..2672e0d3f 100644 --- a/components/validator/issuer.go +++ b/components/validator/issuer.go @@ -11,9 +11,6 @@ func issueValidatorBlock(ctx context.Context) { // Get the main engine instance in case it changes mid-execution. engineInstance := deps.Protocol.MainEngineInstance() - // Get the latest commitment from the engine before to avoid race conditions if something is committed after we fix block issuing time. - latestCommitment := engineInstance.Storage.Settings().LatestCommitment() - blockIssuingTime := time.Now() nextBroadcast := blockIssuingTime.Add(ParamsValidator.CommitteeBroadcastInterval) @@ -39,7 +36,6 @@ func issueValidatorBlock(ctx context.Context) { validatorAccount, blockfactory.WithValidationBlockHeaderOptions( blockfactory.WithIssuingTime(blockIssuingTime), - blockfactory.WithSlotCommitment(latestCommitment.Commitment()), ), blockfactory.WithProtocolParametersHash(protocolParametersHash), blockfactory.WithHighestSupportedVersion(deps.Protocol.LatestAPI().Version()), @@ -63,5 +59,4 @@ func issueValidatorBlock(ctx context.Context) { } Component.LogDebugf("Issued validator block: %s - commitment %s %d - latest finalized slot %d", modelBlock.ID(), modelBlock.ProtocolBlock().SlotCommitmentID, modelBlock.ProtocolBlock().SlotCommitmentID.Slot(), modelBlock.ProtocolBlock().LatestFinalizedSlot) - } From b0dd8dc7303dce3653c35808c5d14401c2421236 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:23:50 +0200 Subject: [PATCH 29/46] Lock createCommitment to avoid race between warpsync and acceptaance --- .../engine/notarization/slotnotarization/manager.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/protocol/engine/notarization/slotnotarization/manager.go b/pkg/protocol/engine/notarization/slotnotarization/manager.go index 09f7edcda..e6de2e364 100644 --- a/pkg/protocol/engine/notarization/slotnotarization/manager.go +++ b/pkg/protocol/engine/notarization/slotnotarization/manager.go @@ -6,6 +6,7 @@ import ( "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/hive.go/runtime/module" + "github.com/iotaledger/hive.go/runtime/syncutils" "github.com/iotaledger/hive.go/runtime/workerpool" "github.com/iotaledger/hive.go/serializer/v2/serix" "github.com/iotaledger/iota-core/pkg/model" @@ -39,6 +40,8 @@ type Manager struct { minCommittableAge iotago.SlotIndex apiProvider iotago.APIProvider + commitmentMutex syncutils.Mutex + module.Module } @@ -164,6 +167,9 @@ func (m *Manager) isCommittable(index, acceptedBlockIndex iotago.SlotIndex) bool } func (m *Manager) createCommitment(slot iotago.SlotIndex) (*model.Commitment, error) { + m.commitmentMutex.Lock() + defer m.commitmentMutex.Unlock() + latestCommitment := m.storage.Settings().LatestCommitment() if slot != latestCommitment.Slot()+1 { return nil, ierrors.Errorf("cannot create commitment for slot %d, latest commitment is for slot %d", slot, latestCommitment.Slot()) From 4aff27cde857b4833fdc591ede132fdbb929b52b Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:21:09 +0200 Subject: [PATCH 30/46] Fix loss of acceptance tests --- pkg/tests/loss_of_acceptance_test.go | 14 ++++++++------ pkg/testsuite/mock/acceptance_loss.go | 22 +++++++++++----------- pkg/testsuite/mock/blockissuer.go | 24 +++++++++++++----------- pkg/testsuite/testsuite_issue_blocks.go | 3 ++- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/pkg/tests/loss_of_acceptance_test.go b/pkg/tests/loss_of_acceptance_test.go index 82e4360f3..e5bce77bb 100644 --- a/pkg/tests/loss_of_acceptance_test.go +++ b/pkg/tests/loss_of_acceptance_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/iotaledger/iota-core/pkg/blockfactory" "github.com/iotaledger/iota-core/pkg/protocol" "github.com/iotaledger/iota-core/pkg/testsuite" "github.com/iotaledger/iota-core/pkg/testsuite/mock" @@ -26,6 +25,7 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { ) defer ts.Shutdown() + ts.AddBasicBlockIssuer("default") node0 := ts.AddValidatorNode("node0") ts.AddValidatorNode("node1") ts.AddNode("node2") @@ -39,7 +39,7 @@ func TestLossOfAcceptanceFromGenesis(t *testing.T) { // Revive chain on node0. { block0 := ts.IssueValidationBlock("block0", node0, - blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), + mock.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(50)), ) require.EqualValues(t, 48, ts.Block("block0").SlotCommitmentID().Slot()) // Reviving the chain should select one parent from the last committed slot. @@ -103,6 +103,7 @@ func TestLossOfAcceptanceFromSnapshot(t *testing.T) { ) defer ts.Shutdown() + ts.AddBasicBlockIssuer("default") node0 := ts.AddValidatorNode("node0") ts.AddValidatorNode("node1") node2 := ts.AddNode("node2") @@ -125,7 +126,7 @@ func TestLossOfAcceptanceFromSnapshot(t *testing.T) { require.NoError(t, ts.Node("node0").Protocol.MainEngineInstance().WriteSnapshot(snapshotPath)) node0restarted = ts.AddNode("node0-restarted") - node0restarted.CopyIdentityFromNode(node0) + node0restarted.Validator = node0.Validator node0restarted.Initialize(true, protocol.WithSnapshotPath(snapshotPath), protocol.WithBaseDirectory(ts.Directory.PathWithCreate(node0restarted.Name)), @@ -141,7 +142,7 @@ func TestLossOfAcceptanceFromSnapshot(t *testing.T) { // Revive chain on node0-restarted. { block0 := ts.IssueValidationBlock("block0", node0restarted, - blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), + mock.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), ) require.EqualValues(t, 18, block0.SlotCommitmentID().Slot()) // Reviving the chain should select one parent from the last committed slot. @@ -189,6 +190,7 @@ func TestLossOfAcceptanceWithRestartFromDisk(t *testing.T) { ) defer ts.Shutdown() + ts.AddBasicBlockIssuer("default") node0 := ts.AddValidatorNode("node0") ts.AddValidatorNode("node1") node2 := ts.AddNode("node2") @@ -213,7 +215,7 @@ func TestLossOfAcceptanceWithRestartFromDisk(t *testing.T) { var node0restarted *mock.Node { node0restarted = ts.AddNode("node0-restarted") - node0restarted.CopyIdentityFromNode(node0) + node0restarted.Validator = node0.Validator node0restarted.Initialize(true, protocol.WithBaseDirectory(ts.Directory.PathWithCreate(node0.Name)), ) @@ -223,7 +225,7 @@ func TestLossOfAcceptanceWithRestartFromDisk(t *testing.T) { // Revive chain on node0-restarted. { block0 := ts.IssueValidationBlock("block0", node0restarted, - blockfactory.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), + mock.WithIssuingTime(ts.API.TimeProvider().SlotStartTime(20)), ) require.EqualValues(t, 18, block0.SlotCommitmentID().Slot()) // Reviving the chain should select one parent from the last committed slot. diff --git a/pkg/testsuite/mock/acceptance_loss.go b/pkg/testsuite/mock/acceptance_loss.go index 076a5b53c..8e5909c7e 100644 --- a/pkg/testsuite/mock/acceptance_loss.go +++ b/pkg/testsuite/mock/acceptance_loss.go @@ -1,4 +1,4 @@ -package blockfactory +package mock import ( "time" @@ -7,13 +7,13 @@ import ( iotago "github.com/iotaledger/iota.go/v4" ) -func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, iotago.BlockID, error) { - lastCommittedSlot := i.protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() - apiForSlot := i.protocol.APIForSlot(lastCommittedSlot) +func (i *BlockIssuer) reviveChain(issuingTime time.Time, node *Node) (*iotago.Commitment, iotago.BlockID, error) { + lastCommittedSlot := node.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() + apiForSlot := node.Protocol.APIForSlot(lastCommittedSlot) // Get a rootblock as recent as possible for the parent. - parentBlockID := iotago.EmptyBlockID() - for rootBlock := range i.protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() { + parentBlockID := iotago.EmptyBlockID + for rootBlock := range node.Protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() { if rootBlock.Slot() > parentBlockID.Slot() { parentBlockID = rootBlock } @@ -29,17 +29,17 @@ func (i *BlockIssuer) reviveChain(issuingTime time.Time) (*iotago.Commitment, io // Force commitments until minCommittableAge relative to the block's issuing time. We basically "pretend" that // this block was already accepted at the time of issuing so that we have a commitment to reference. if issuingSlot < apiForSlot.ProtocolParameters().MinCommittableAge() { // Should never happen as we're beyond maxCommittableAge which is > minCommittableAge. - return nil, iotago.EmptyBlockID(), ierrors.Errorf("issuing slot %d is smaller than min committable age %d", issuingSlot, apiForSlot.ProtocolParameters().MinCommittableAge()) + return nil, iotago.EmptyBlockID, ierrors.Errorf("issuing slot %d is smaller than min committable age %d", issuingSlot, apiForSlot.ProtocolParameters().MinCommittableAge()) } commitUntilSlot := issuingSlot - apiForSlot.ProtocolParameters().MinCommittableAge() - if err := i.protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { - return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to force commit until slot %d", commitUntilSlot) + if err := node.Protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { + return nil, iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to force commit until slot %d", commitUntilSlot) } - commitment, err := i.protocol.MainEngineInstance().Storage.Commitments().Load(commitUntilSlot) + commitment, err := node.Protocol.MainEngineInstance().Storage.Commitments().Load(commitUntilSlot) if err != nil { - return nil, iotago.EmptyBlockID(), ierrors.Wrapf(err, "failed to commit until slot %d to revive chain", commitUntilSlot) + return nil, iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to commit until slot %d to revive chain", commitUntilSlot) } return commitment.Commitment(), parentBlockID, nil diff --git a/pkg/testsuite/mock/blockissuer.go b/pkg/testsuite/mock/blockissuer.go index a103e095a..91d008f6f 100644 --- a/pkg/testsuite/mock/blockissuer.go +++ b/pkg/testsuite/mock/blockissuer.go @@ -91,7 +91,7 @@ func (i *BlockIssuer) Shutdown() { i.workerPool.ShutdownComplete.Wait() } -func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, issuerAccount Account, node *Node, opts ...options.Option[ValidatorBlockParams]) *blocks.Block { +func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, issuerAccount Account, node *Node, opts ...options.Option[ValidatorBlockParams]) (*blocks.Block, error) { blockParams := options.Apply(&ValidatorBlockParams{}, opts) if blockParams.BlockHeader.IssuingTime == nil { @@ -101,9 +101,9 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, i if blockParams.BlockHeader.SlotCommitment == nil { var err error - blockParams.BlockHeader.SlotCommitment, err = i.getAddressableCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) + blockParams.BlockHeader.SlotCommitment, err = i.getAddressableCommitment(node.Protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime), node) if err != nil && ierrors.Is(err, ErrBlockTooRecent) { - commitment, parentID, err := i.reviveChain(*blockParams.BlockHeader.IssuingTime) + commitment, parentID, err := i.reviveChain(*blockParams.BlockHeader.IssuingTime, node) if err != nil { return nil, ierrors.Wrap(err, "failed to revive chain") } @@ -177,11 +177,12 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, i modelBlock.ID().RegisterAlias(alias) - return blocks.NewBlock(modelBlock) + return blocks.NewBlock(modelBlock), nil } func (i *BlockIssuer) IssueValidationBlock(ctx context.Context, alias string, node *Node, opts ...options.Option[ValidatorBlockParams]) *blocks.Block { - block := i.CreateValidationBlock(ctx, alias, NewEd25519Account(i.AccountID, i.privateKey), node, opts...) + block, err := i.CreateValidationBlock(ctx, alias, NewEd25519Account(i.AccountID, i.privateKey), node, opts...) + require.NoError(i.Testing, err) require.NoError(i.Testing, i.IssueBlock(block.ModelBlock(), node)) @@ -199,7 +200,7 @@ func (i *BlockIssuer) retrieveAPI(blockParams *BlockHeaderParams, node *Node) (i } // CreateBlock creates a new block with the options. -func (i *BlockIssuer) CreateBasicBlock(ctx context.Context, alias string, node *Node, opts ...options.Option[BasicBlockParams]) *blocks.Block { +func (i *BlockIssuer) CreateBasicBlock(ctx context.Context, alias string, node *Node, opts ...options.Option[BasicBlockParams]) (*blocks.Block, error) { blockParams := options.Apply(&BasicBlockParams{}, opts) if blockParams.BlockHeader.IssuingTime == nil { @@ -209,7 +210,7 @@ func (i *BlockIssuer) CreateBasicBlock(ctx context.Context, alias string, node * if blockParams.BlockHeader.SlotCommitment == nil { var err error - blockParams.BlockHeader.SlotCommitment, err = i.getAddressableCommitment(i.protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime)) + blockParams.BlockHeader.SlotCommitment, err = i.getAddressableCommitment(node.Protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime), node) if err != nil { return nil, ierrors.Wrap(err, "error getting commitment") } @@ -269,11 +270,12 @@ func (i *BlockIssuer) CreateBasicBlock(ctx context.Context, alias string, node * modelBlock.ID().RegisterAlias(alias) - return blocks.NewBlock(modelBlock) + return blocks.NewBlock(modelBlock), err } func (i *BlockIssuer) IssueBasicBlock(ctx context.Context, alias string, node *Node, opts ...options.Option[BasicBlockParams]) *blocks.Block { - block := i.CreateBasicBlock(ctx, alias, node, opts...) + block, err := i.CreateBasicBlock(ctx, alias, node, opts...) + require.NoError(i.Testing, err) require.NoErrorf(i.Testing, i.IssueBlock(block.ModelBlock(), node), "%s > failed to issue block with alias %s", i.Name, alias) @@ -481,7 +483,7 @@ func (i *BlockIssuer) setDefaultBlockParams(blockParams *BlockHeaderParams, node if blockParams.SlotCommitment == nil { var err error - blockParams.SlotCommitment, err = i.getCommitment(node.Protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.IssuingTime), node) + blockParams.SlotCommitment, err = i.getAddressableCommitment(node.Protocol.CurrentAPI().TimeProvider().SlotFromTime(*blockParams.IssuingTime), node) if err != nil { return ierrors.Wrap(err, "error getting commitment") } @@ -563,7 +565,7 @@ func (i *BlockIssuer) IssueBlock(block *model.Block, node *Node) error { } if _, isValidationBlock := block.ValidationBlock(); isValidationBlock { - _ = i.protocol.MainEngineInstance().Storage.Settings().SetLatestIssuedValidationBlock(block) + _ = node.Protocol.MainEngineInstance().Storage.Settings().SetLatestIssuedValidationBlock(block) } i.events.BlockIssued.Trigger(block) diff --git a/pkg/testsuite/testsuite_issue_blocks.go b/pkg/testsuite/testsuite_issue_blocks.go index 08c727d5a..4d47c232e 100644 --- a/pkg/testsuite/testsuite_issue_blocks.go +++ b/pkg/testsuite/testsuite_issue_blocks.go @@ -65,7 +65,8 @@ func (t *TestSuite) CreateBasicBlock(alias string, blockIssuer *mock.BlockIssuer t.mutex.Lock() defer t.mutex.Unlock() - block := blockIssuer.CreateBasicBlock(context.Background(), alias, node, blockOpts...) + block, err := blockIssuer.CreateBasicBlock(context.Background(), alias, node, blockOpts...) + require.NoError(t.Testing, err) t.registerBlock(alias, block) } From be357dea787156d1724e79ec40b85d4e427806d7 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:38:30 +0200 Subject: [PATCH 31/46] Adapt reviveChain logic from mock.BlockIssuer to Validator component --- components/validator/issuer.go | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/components/validator/issuer.go b/components/validator/issuer.go index f445fcf8b..6c05d67a3 100644 --- a/components/validator/issuer.go +++ b/components/validator/issuer.go @@ -4,11 +4,14 @@ import ( "context" "time" + "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota-core/pkg/model" iotago "github.com/iotaledger/iota.go/v4" "github.com/iotaledger/iota.go/v4/builder" ) +var ErrBlockTooRecent = ierrors.New("block is too recent compared to latest commitment") + func issueValidatorBlock(ctx context.Context) { // Get the main engine instance in case it changes mid-execution. engineInstance := deps.Protocol.MainEngineInstance() @@ -36,10 +39,28 @@ func issueValidatorBlock(ctx context.Context) { parents := engineInstance.TipSelection.SelectTips(iotago.BlockTypeValidationMaxParents) + addressableCommitment, err := getAddressableCommitment(deps.Protocol.CurrentAPI().TimeProvider().SlotFromTime(blockIssuingTime)) + if err != nil && ierrors.Is(err, ErrBlockTooRecent) { + commitment, parentID, reviveChainErr := reviveChain(blockIssuingTime) + if reviveChainErr != nil { + Component.LogError("error reviving chain: %s", reviveChainErr.Error()) + return + } + + addressableCommitment = commitment + parents = make(model.ParentReferences) + parents[iotago.StrongParentType] = []iotago.BlockID{parentID} + } else if err != nil { + Component.LogWarnf("error getting commitment: %s", err.Error()) + + return + } + // create the validation block here using the validation block builder from iota.go validationBlock, err := builder.NewValidationBlockBuilder(deps.Protocol.CurrentAPI()). IssuingTime(blockIssuingTime). ProtocolParametersHash(protocolParametersHash). + SlotCommitmentID(addressableCommitment.MustID()). HighestSupportedVersion(deps.Protocol.LatestAPI().Version()). LatestFinalizedSlot(engineInstance.SyncManager.LatestFinalizedSlot()). StrongParents(parents[iotago.StrongParentType]). @@ -74,3 +95,66 @@ func issueValidatorBlock(ctx context.Context) { Component.LogDebugf("Issued validator block: %s - commitment %s %d - latest finalized slot %d", modelBlock.ID(), modelBlock.ProtocolBlock().SlotCommitmentID, modelBlock.ProtocolBlock().SlotCommitmentID.Slot(), modelBlock.ProtocolBlock().LatestFinalizedSlot) } + +func reviveChain(issuingTime time.Time) (*iotago.Commitment, iotago.BlockID, error) { + lastCommittedSlot := deps.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() + apiForSlot := deps.Protocol.APIForSlot(lastCommittedSlot) + + // Get a rootblock as recent as possible for the parent. + parentBlockID := iotago.EmptyBlockID + for rootBlock := range deps.Protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() { + if rootBlock.Slot() > parentBlockID.Slot() { + parentBlockID = rootBlock + } + + // Exit the loop if we found a rootblock in the last committed slot (which is the highest we can get). + if parentBlockID.Slot() == lastCommittedSlot { + break + } + } + + issuingSlot := apiForSlot.TimeProvider().SlotFromTime(issuingTime) + + // Force commitments until minCommittableAge relative to the block's issuing time. We basically "pretend" that + // this block was already accepted at the time of issuing so that we have a commitment to reference. + if issuingSlot < apiForSlot.ProtocolParameters().MinCommittableAge() { // Should never happen as we're beyond maxCommittableAge which is > minCommittableAge. + return nil, iotago.EmptyBlockID, ierrors.Errorf("issuing slot %d is smaller than min committable age %d", issuingSlot, apiForSlot.ProtocolParameters().MinCommittableAge()) + } + commitUntilSlot := issuingSlot - apiForSlot.ProtocolParameters().MinCommittableAge() + + if err := deps.Protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { + return nil, iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to force commit until slot %d", commitUntilSlot) + } + + commitment, err := deps.Protocol.MainEngineInstance().Storage.Commitments().Load(commitUntilSlot) + if err != nil { + return nil, iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to commit until slot %d to revive chain", commitUntilSlot) + } + + return commitment.Commitment(), parentBlockID, nil +} + +func getAddressableCommitment(blockSlot iotago.SlotIndex) (*iotago.Commitment, error) { + protoParams := deps.Protocol.CurrentAPI().ProtocolParameters() + commitment := deps.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment() + + if blockSlot > commitment.Slot+protoParams.MaxCommittableAge() { + return nil, ierrors.Wrapf(ErrBlockTooRecent, "can't issue block: block slot %d is too far in the future, latest commitment is %d", blockSlot, commitment.Slot) + } + + if blockSlot < commitment.Slot+protoParams.MinCommittableAge() { + if blockSlot < protoParams.MinCommittableAge() || commitment.Slot < protoParams.MinCommittableAge() { + return commitment, nil + } + + commitmentSlot := commitment.Slot - protoParams.MinCommittableAge() + loadedCommitment, err := deps.Protocol.MainEngineInstance().Storage.Commitments().Load(commitmentSlot) + if err != nil { + return nil, ierrors.Wrapf(err, "error loading valid commitment of slot %d according to minCommittableAge from storage", commitmentSlot) + } + + return loadedCommitment.Commitment(), nil + } + + return commitment, nil +} From d628318dbc027b7756c0d01578f60284e512eee4 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:53:21 +0200 Subject: [PATCH 32/46] Provide BlockHandler dependency from RestAPI component --- components/restapi/component.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/restapi/component.go b/components/restapi/component.go index c0289ef20..d6dc4b470 100644 --- a/components/restapi/component.go +++ b/components/restapi/component.go @@ -15,6 +15,7 @@ import ( "github.com/iotaledger/hive.go/app" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/inx-app/pkg/httpserver" + "github.com/iotaledger/iota-core/pkg/blockhandler" "github.com/iotaledger/iota-core/pkg/daemon" "github.com/iotaledger/iota-core/pkg/jwt" protocolpkg "github.com/iotaledger/iota-core/pkg/protocol" @@ -99,6 +100,12 @@ func provide(c *dig.Container) error { Component.LogPanic(err) } + if err := c.Provide(func(deps dependencies) *blockhandler.BlockHandler { + return blockhandler.New(deps.Protocol) + }); err != nil { + Component.LogPanic(err) + } + return nil } From 8cddbe40f92aa3d83cfcfe7ce719aee090bcbcf8 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:53:35 +0200 Subject: [PATCH 33/46] --blockIssuer.rateSetterEnabled parameter has been dropped --- tools/docker-network/docker-compose.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/docker-network/docker-compose.yml b/tools/docker-network/docker-compose.yml index ebc264856..e547cb9c1 100644 --- a/tools/docker-network/docker-compose.yml +++ b/tools/docker-network/docker-compose.yml @@ -11,7 +11,6 @@ services: ${COMMON_CONFIG} ${MANUALPEERING_CONFIG} --p2p.identityPrivateKey=08735375679f3d8031353e94282ed1d65119e5c288fe56d6639d9184a3f978fee8febfedff11cc376daea0f59c395ae2e9a870a25ac4e36093000fbf4d0e8f18 - --blockIssuer.rateSetterEnabled=true --validator.enabled=true --validator.ignoreBootstrapped=true --validator.account=0x907c02e9302e0f0571f10f885594e56d8c54ff0708ab7a39bc1b74d396b93b12 @@ -45,7 +44,6 @@ services: ${COMMON_CONFIG} ${MANUALPEERING_CONFIG} --p2p.identityPrivateKey=ba771419c52132a0dfb2521ed18667813f398da159010a55a0a482af939affb92d3338789ad4a07a7631b91791deb11f82ed5dc612822f24275e9f7a313b691f - --blockIssuer.rateSetterEnabled=true --validator.enabled=true --validator.account=0x375358f92cc94750669598b0aaa55a6ff73310b90710e1fad524c0f911be0fea --validator.privateKey=3a5d39f8b60367a17fd54dac2a32c172c8e1fd6cf74ce65f1e13edba565f281705c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064 @@ -70,7 +68,6 @@ services: ${COMMON_CONFIG} ${MANUALPEERING_CONFIG} --p2p.identityPrivateKey=a6261ac049755675ff1437654ca9f83b305055f01ff08c4f039209ef5a4a7d96d06fb61df77a8815209a8f4d204226dee593e50d0ec897ec440a2c1fbde77656 - --blockIssuer.rateSetterEnabled=true --validator.enabled=true --validator.account=0x6aee704f25558e8aa7630fed0121da53074188abc423b3c5810f80be4936eb6e --validator.privateKey=db39d2fde6301d313b108dc9db1ee724d0f405f6fde966bd776365bc5f4a5fb31e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648 From 2abee9d6de4b2bba56cce374b6716d5a8d14599c Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:05:52 +0200 Subject: [PATCH 34/46] Point to a hive.go without queue's PanicOnModificationsAfterShutdown --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index aa05739c2..df8f2be91 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b - github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217 diff --git a/go.sum b/go.sum index 35e2e042d..2aa469e85 100644 --- a/go.sum +++ b/go.sum @@ -297,6 +297,8 @@ github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b h1:fYJ2y github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b h1:skHzoSAI2TNmoJwgW7/aq/Il3JZ5Fa9D5d9U41oWKYg= github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 h1:2q4ksrGfCFs4noBlzUgODq4kaf3Zl2nKsOT8Zdo38zY= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b h1:6anjtWbaCszD5h43psnE8lsgIM0etpjr62ZlN59t0H8= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b h1:cc9VsDzLxPAaC8fj96EA1bJxbmrEZndJV+3SmG+HHOs= From a281a2917124e00caca3349a429ac7095e71f7fb Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:52:09 +0900 Subject: [PATCH 35/46] go.mod tidy --- go.sum | 2 -- tools/evil-spammer/go.mod | 2 +- tools/evil-spammer/go.sum | 4 ++-- tools/gendoc/go.mod | 2 +- tools/gendoc/go.sum | 4 ++-- tools/genesis-snapshot/go.mod | 2 +- tools/genesis-snapshot/go.sum | 4 ++-- tools/genesis-snapshot/presets/presets.go | 6 ++---- 8 files changed, 11 insertions(+), 15 deletions(-) diff --git a/go.sum b/go.sum index 2aa469e85..a6489b160 100644 --- a/go.sum +++ b/go.sum @@ -295,8 +295,6 @@ github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b h1:UnWVwiVj/ github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b h1:fYJ2yrb9cYyoLzlEIxLsdPSSufxh0Xw/AoawlGdpdU8= github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b h1:skHzoSAI2TNmoJwgW7/aq/Il3JZ5Fa9D5d9U41oWKYg= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 h1:2q4ksrGfCFs4noBlzUgODq4kaf3Zl2nKsOT8Zdo38zY= github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b h1:6anjtWbaCszD5h43psnE8lsgIM0etpjr62ZlN59t0H8= diff --git a/tools/evil-spammer/go.mod b/tools/evil-spammer/go.mod index 08e5d1d90..16f4be851 100644 --- a/tools/evil-spammer/go.mod +++ b/tools/evil-spammer/go.mod @@ -14,7 +14,7 @@ require ( github.com/iotaledger/hive.go/ierrors v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b - github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota-core/tools/genesis-snapshot v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c diff --git a/tools/evil-spammer/go.sum b/tools/evil-spammer/go.sum index 9bbd459ce..d13b88129 100644 --- a/tools/evil-spammer/go.sum +++ b/tools/evil-spammer/go.sum @@ -189,8 +189,8 @@ github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b h1:UnWVwiVj/ github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b h1:fYJ2yrb9cYyoLzlEIxLsdPSSufxh0Xw/AoawlGdpdU8= github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b h1:skHzoSAI2TNmoJwgW7/aq/Il3JZ5Fa9D5d9U41oWKYg= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 h1:2q4ksrGfCFs4noBlzUgODq4kaf3Zl2nKsOT8Zdo38zY= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b h1:6anjtWbaCszD5h43psnE8lsgIM0etpjr62ZlN59t0H8= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b h1:cc9VsDzLxPAaC8fj96EA1bJxbmrEZndJV+3SmG+HHOs= diff --git a/tools/gendoc/go.mod b/tools/gendoc/go.mod index 3d6a97cb4..0b40ffa41 100644 --- a/tools/gendoc/go.mod +++ b/tools/gendoc/go.mod @@ -67,7 +67,7 @@ require ( github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 // indirect github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b // indirect github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b // indirect - github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b // indirect + github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 // indirect github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b // indirect github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b // indirect github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217 // indirect diff --git a/tools/gendoc/go.sum b/tools/gendoc/go.sum index 8383833c9..df4fe192e 100644 --- a/tools/gendoc/go.sum +++ b/tools/gendoc/go.sum @@ -301,8 +301,8 @@ github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b h1:UnWVwiVj/ github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b h1:fYJ2yrb9cYyoLzlEIxLsdPSSufxh0Xw/AoawlGdpdU8= github.com/iotaledger/hive.go/logger v0.0.0-20231005142627-86973b2edb3b/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b h1:skHzoSAI2TNmoJwgW7/aq/Il3JZ5Fa9D5d9U41oWKYg= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 h1:2q4ksrGfCFs4noBlzUgODq4kaf3Zl2nKsOT8Zdo38zY= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b h1:6anjtWbaCszD5h43psnE8lsgIM0etpjr62ZlN59t0H8= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b h1:cc9VsDzLxPAaC8fj96EA1bJxbmrEZndJV+3SmG+HHOs= diff --git a/tools/genesis-snapshot/go.mod b/tools/genesis-snapshot/go.mod index 72a019bb7..cf3a59336 100644 --- a/tools/genesis-snapshot/go.mod +++ b/tools/genesis-snapshot/go.mod @@ -8,7 +8,7 @@ require ( github.com/iotaledger/hive.go/crypto v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/hive.go/ierrors v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b - github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c github.com/mr-tron/base58 v1.2.0 diff --git a/tools/genesis-snapshot/go.sum b/tools/genesis-snapshot/go.sum index 2f45945f8..5eca70592 100644 --- a/tools/genesis-snapshot/go.sum +++ b/tools/genesis-snapshot/go.sum @@ -44,8 +44,8 @@ github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 h1:XCYv github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b h1:UnWVwiVj/BceDDL9J/nCAVRlUDVnbTsCf7PI4lWrdfU= github.com/iotaledger/hive.go/lo v0.0.0-20231005142627-86973b2edb3b/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b h1:skHzoSAI2TNmoJwgW7/aq/Il3JZ5Fa9D5d9U41oWKYg= -github.com/iotaledger/hive.go/runtime v0.0.0-20231005142627-86973b2edb3b/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62 h1:2q4ksrGfCFs4noBlzUgODq4kaf3Zl2nKsOT8Zdo38zY= +github.com/iotaledger/hive.go/runtime v0.0.0-20231009160305-04d9e5bb7e62/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b h1:6anjtWbaCszD5h43psnE8lsgIM0etpjr62ZlN59t0H8= github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b h1:cc9VsDzLxPAaC8fj96EA1bJxbmrEZndJV+3SmG+HHOs= diff --git a/tools/genesis-snapshot/presets/presets.go b/tools/genesis-snapshot/presets/presets.go index ab7b68bb2..01fa4bf6a 100644 --- a/tools/genesis-snapshot/presets/presets.go +++ b/tools/genesis-snapshot/presets/presets.go @@ -1,8 +1,6 @@ package presets import ( - "time" - "golang.org/x/crypto/blake2b" "github.com/iotaledger/hive.go/crypto/ed25519" @@ -22,7 +20,7 @@ var Base = []options.Option[snapshotcreator.Options]{ iotago.NewV3ProtocolParameters( iotago.WithNetworkOptions("default", "rms"), iotago.WithSupplyOptions(10_000_000_000, 100, 1, 10, 100, 100, 100), - iotago.WithTimeProviderOptions(time.Now().Unix(), 10, 13), + iotago.WithTimeProviderOptions(1696841745, 10, 13), iotago.WithLivenessOptions(30, 30, 7, 14, 30), // increase/decrease threshold = fraction * slotDurationInSeconds * schedulerRate iotago.WithCongestionControlOptions(500, 500, 500, 800000, 500000, 100000, 1000, 100), @@ -96,7 +94,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ iotago.NewV3ProtocolParameters( iotago.WithNetworkOptions("docker", "rms"), iotago.WithSupplyOptions(10_000_000_000, 1, 1, 10, 100, 100, 100), - iotago.WithTimeProviderOptions(time.Now().Unix(), 10, 13), + iotago.WithTimeProviderOptions(1696908344, 10, 13), iotago.WithLivenessOptions(30, 30, 7, 14, 30), // increase/decrease threshold = fraction * slotDurationInSeconds * schedulerRate iotago.WithCongestionControlOptions(500, 500, 500, 800000, 500000, 100000, 1000, 100), From 5d4018ac1c189d70a861ac9de492485b418d5bd5 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:59:39 +0900 Subject: [PATCH 36/46] Fix shutdown issue of engine by unhooking AcceptedBlockProcessed event when NotarizationManager is shutdown --- .../engine/notarization/slotnotarization/manager.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/protocol/engine/notarization/slotnotarization/manager.go b/pkg/protocol/engine/notarization/slotnotarization/manager.go index e6de2e364..80081f148 100644 --- a/pkg/protocol/engine/notarization/slotnotarization/manager.go +++ b/pkg/protocol/engine/notarization/slotnotarization/manager.go @@ -26,8 +26,9 @@ type Manager struct { events *notarization.Events slotMutations *SlotMutations - workers *workerpool.Group - errorHandler func(error) + workers *workerpool.Group + errorHandler func(error) + acceptedBlockProcessedDetach func() attestation attestation.Attestations ledger ledger.Ledger @@ -62,14 +63,14 @@ func NewProvider() module.Provider[*engine.Engine, notarization.Notarization] { wpBlocks := m.workers.CreatePool("Blocks", 1) // Using just 1 worker to avoid contention - e.Events.AcceptedBlockProcessed.Hook(func(block *blocks.Block) { + m.acceptedBlockProcessedDetach = e.Events.AcceptedBlockProcessed.Hook(func(block *blocks.Block) { if err := m.notarizeAcceptedBlock(block); err != nil { m.errorHandler(ierrors.Wrapf(err, "failed to add accepted block %s to slot", block.ID())) } m.tryCommitUntil(block.ID().Slot()) block.SetNotarized() - }, event.WithWorkerPool(wpBlocks)) + }, event.WithWorkerPool(wpBlocks)).Unhook e.Events.Notarization.LinkTo(m.events) @@ -93,6 +94,10 @@ func NewManager(minCommittableAge iotago.SlotIndex, workers *workerpool.Group, e func (m *Manager) Shutdown() { m.TriggerStopped() + // Alternative 2 + if m.acceptedBlockProcessedDetach != nil { + m.acceptedBlockProcessedDetach() + } m.workers.Shutdown() } From 9ab06090dd5c17793089505366b044b06ec38f5d Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:59:58 +0900 Subject: [PATCH 37/46] Fix some string display issues in metrics and dashboard --- components/dashboard/explorer_routes.go | 10 +++++----- components/metrics/metrics_commitments.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/dashboard/explorer_routes.go b/components/dashboard/explorer_routes.go index fb9c6ef6e..ade3c3622 100644 --- a/components/dashboard/explorer_routes.go +++ b/components/dashboard/explorer_routes.go @@ -118,7 +118,7 @@ func createExplorerBlock(block *model.Block, cachedBlock *blocks.Block, metadata SolidificationTimestamp: 0, IssuanceTimestamp: iotaBlk.IssuingTime.Unix(), SequenceNumber: 0, - IssuerID: iotaBlk.IssuerID.String(), + IssuerID: iotaBlk.IssuerID.ToHex(), Signature: hexutil.EncodeHex(sigBytes), StrongParents: iotaBlk.Block.StrongParentIDs().ToHex(), WeakParents: iotaBlk.Block.WeakParentIDs().ToHex(), @@ -164,16 +164,16 @@ func createExplorerBlock(block *model.Block, cachedBlock *blocks.Block, metadata t.Scheduled = cachedBlock.IsScheduled() t.ObjectivelyInvalid = cachedBlock.IsInvalid() t.StrongChildren = lo.Map(cachedBlock.StrongChildren(), func(childBlock *blocks.Block) string { - return childBlock.ID().String() + return childBlock.ID().ToHex() }) t.WeakChildren = lo.Map(cachedBlock.WeakChildren(), func(childBlock *blocks.Block) string { - return childBlock.ID().String() + return childBlock.ID().ToHex() }) t.LikedInsteadChildren = lo.Map(cachedBlock.ShallowLikeChildren(), func(childBlock *blocks.Block) string { - return childBlock.ID().String() + return childBlock.ID().ToHex() }) t.ConflictIDs = lo.Map(cachedBlock.ConflictIDs().ToSlice(), func(conflictID iotago.TransactionID) string { - return conflictID.String() + return conflictID.ToHex() }) } else { switch metadata.BlockState { diff --git a/components/metrics/metrics_commitments.go b/components/metrics/metrics_commitments.go index 595f914cd..273dc6a6e 100644 --- a/components/metrics/metrics_commitments.go +++ b/components/metrics/metrics_commitments.go @@ -30,7 +30,7 @@ var CommitmentsMetrics = collector.NewCollection(commitmentsNamespace, collector.WithPruningDelay(10*time.Minute), collector.WithInitFunc(func() { deps.Protocol.Events.Engine.Notarization.SlotCommitted.Hook(func(details *notarization.SlotCommittedDetails) { - deps.Collector.Update(commitmentsNamespace, latestCommitment, float64(details.Commitment.ID().Slot()), details.Commitment.ID().String()) + deps.Collector.Update(commitmentsNamespace, latestCommitment, float64(details.Commitment.ID().Slot()), "C "+details.Commitment.ID().ToHex()) }, event.WithWorkerPool(Component.WorkerPool)) }), )), From 075b5211ca7fa841c395b329439676d78dd6164f Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Fri, 6 Oct 2023 12:07:50 +0200 Subject: [PATCH 38/46] Reactive Booker --- pkg/protocol/engine/blocks/block.go | 17 +++-- .../engine/booker/inmemorybooker/booker.go | 71 ++++++++----------- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index 4d31deb55..87ba51bc8 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -20,7 +20,7 @@ type Block struct { missing bool missingBlockID iotago.BlockID solid bool - invalid bool + invalid reactive.Variable[bool] strongChildren []*Block weakChildren []*Block shallowLikeChildren []*Block @@ -75,7 +75,6 @@ func (r *rootBlock) String() string { // NewBlock creates a new Block with the given options. func NewBlock(data *model.Block) *Block { - return &Block{ witnesses: ds.NewSet[account.SeatIndex](), conflictIDs: ds.NewSet[iotago.TransactionID](), @@ -83,6 +82,7 @@ func NewBlock(data *model.Block) *Block { acceptanceRatifiers: ds.NewSet[account.SeatIndex](), confirmationRatifiers: ds.NewSet[account.SeatIndex](), modelBlock: data, + invalid: reactive.NewVariable[bool](), booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), notarized: reactive.NewVariable[bool](), @@ -104,6 +104,7 @@ func NewRootBlock(blockID iotago.BlockID, commitmentID iotago.CommitmentID, issu issuingTime: issuingTime, }, solid: true, + invalid: reactive.NewVariable[bool](), booked: reactive.NewVariable[bool](), preAccepted: true, accepted: reactive.NewVariable[bool](), @@ -128,6 +129,7 @@ func NewMissingBlock(blockID iotago.BlockID) *Block { payloadConflictIDs: ds.NewSet[iotago.TransactionID](), acceptanceRatifiers: ds.NewSet[account.SeatIndex](), confirmationRatifiers: ds.NewSet[account.SeatIndex](), + invalid: reactive.NewVariable[bool](), booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), notarized: reactive.NewVariable[bool](), @@ -261,12 +263,17 @@ func (b *Block) IsSolid() (isSolid bool) { return b.solid } +// Invalid returns a reactive variable that is true if the Block was marked as invalid. +func (b *Block) Invalid() (invalid reactive.Variable[bool]) { + return b.invalid +} + // IsInvalid returns true if the Block was marked as invalid. func (b *Block) IsInvalid() (isInvalid bool) { b.mutex.RLock() defer b.mutex.RUnlock() - return b.invalid + return b.invalid.Get() } // Children returns the children of the Block. @@ -329,11 +336,11 @@ func (b *Block) SetInvalid() (wasUpdated bool) { b.mutex.Lock() defer b.mutex.Unlock() - if b.invalid { + if b.invalid.Get() { return false } - b.invalid = true + b.invalid.Set(true) return true } diff --git a/pkg/protocol/engine/booker/inmemorybooker/booker.go b/pkg/protocol/engine/booker/inmemorybooker/booker.go index 8b360baf6..5e67513ca 100644 --- a/pkg/protocol/engine/booker/inmemorybooker/booker.go +++ b/pkg/protocol/engine/booker/inmemorybooker/booker.go @@ -1,7 +1,8 @@ package inmemorybooker import ( - "github.com/iotaledger/hive.go/core/causalorder" + "sync/atomic" + "github.com/iotaledger/hive.go/ds" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/lo" @@ -21,8 +22,6 @@ import ( type Booker struct { events *booker.Events - bookingOrder *causalorder.CausalOrder[iotago.SlotIndex, iotago.BlockID, *blocks.Block] - workers *workerpool.Group blockCache *blocks.Blocks @@ -79,29 +78,17 @@ func New(workers *workerpool.Group, apiProvider iotago.APIProvider, blockCache * blockCache: blockCache, workers: workers, errorHandler: errorHandler, - }, opts, func(b *Booker) { - b.bookingOrder = causalorder.New( - workers.CreatePool("BookingOrder", 2), - blockCache.Block, - (*blocks.Block).IsBooked, - b.book, - b.markInvalid, - (*blocks.Block).Parents, - causalorder.WithReferenceValidator[iotago.SlotIndex, iotago.BlockID](b.isReferenceValid), - ) - - blockCache.Evict.Hook(b.evict) - }, (*Booker).TriggerConstructed) + }, opts, (*Booker).TriggerConstructed) } var _ booker.Booker = new(Booker) -// Queue checks if payload is solid and then adds the block to a Booker's CausalOrder. +// Queue checks if payload is solid and then sets up the block to react to its parents. func (b *Booker) Queue(block *blocks.Block) error { signedTransactionMetadata, containsTransaction := b.ledger.AttachTransaction(block) if !containsTransaction { - b.bookingOrder.Queue(block) + b.setupBlock(block) return nil } @@ -123,7 +110,7 @@ func (b *Booker) Queue(block *blocks.Block) error { transactionMetadata.OnBooked(func() { block.SetPayloadConflictIDs(transactionMetadata.ConflictIDs()) - b.bookingOrder.Queue(block) + b.setupBlock(block) }) }) @@ -135,12 +122,32 @@ func (b *Booker) Shutdown() { b.workers.Shutdown() } -func (b *Booker) setRetainBlockFailureFunc(retainBlockFailure func(iotago.BlockID, apimodels.BlockFailureReason)) { - b.retainBlockFailure = retainBlockFailure +func (b *Booker) setupBlock(block *blocks.Block) { + var unbookedParentsCount atomic.Int32 + unbookedParentsCount.Store(int32(len(block.Parents()))) + + block.ForEachParent(func(parent iotago.Parent) { + parentBlock, exists := b.blockCache.Block(parent.ID) + if !exists { + panic("cannot setup block without existing parent") + } + + parentBlock.Booked().OnUpdateOnce(func(_, _ bool) { + if unbookedParentsCount.Add(-1) == 0 { + b.book(block) + } + }) + + parentBlock.Invalid().OnUpdateOnce(func(_, _ bool) { + if block.SetInvalid() { + b.events.BlockInvalid.Trigger(block, ierrors.New("block marked as invalid in Booker")) + } + }) + }) } -func (b *Booker) evict(slot iotago.SlotIndex) { - b.bookingOrder.EvictUntil(slot) +func (b *Booker) setRetainBlockFailureFunc(retainBlockFailure func(iotago.BlockID, apimodels.BlockFailureReason)) { + b.retainBlockFailure = retainBlockFailure } func (b *Booker) book(block *blocks.Block) error { @@ -149,7 +156,7 @@ func (b *Booker) book(block *blocks.Block) error { return ierrors.Wrapf(err, "failed to inherit conflicts for block %s", block.ID()) } - // The block is invalid if it carries a conflict that has been orphaned with respect to its commitment. + // The block does not inherit conflicts that have been orphaned with respect to its commitment. for it := conflictsToInherit.Iterator(); it.HasNext(); { conflictID := it.Next() @@ -171,12 +178,6 @@ func (b *Booker) book(block *blocks.Block) error { return nil } -func (b *Booker) markInvalid(block *blocks.Block, err error) { - if block.SetInvalid() { - b.events.BlockInvalid.Trigger(block, ierrors.Wrap(err, "block marked as invalid in Booker")) - } -} - func (b *Booker) inheritConflicts(block *blocks.Block) (conflictIDs ds.Set[iotago.TransactionID], err error) { conflictIDsToInherit := ds.NewSet[iotago.TransactionID]() @@ -217,13 +218,3 @@ func (b *Booker) inheritConflicts(block *blocks.Block) (conflictIDs ds.Set[iotag // Only inherit conflicts that are not yet accepted (aka merge to master). return b.conflictDAG.UnacceptedConflicts(conflictIDsToInherit), nil } - -// isReferenceValid checks if the reference between the child and its parent is valid. -func (b *Booker) isReferenceValid(child *blocks.Block, parent *blocks.Block) (err error) { - if parent.IsInvalid() { - b.retainBlockFailure(child.ID(), apimodels.BlockFailureParentInvalid) - return ierrors.Errorf("parent %s of child %s is marked as invalid", parent.ID(), child.ID()) - } - - return nil -} From df35b2126826b2230cea7e0143fcc94d18b36afc Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Fri, 6 Oct 2023 12:27:40 +0200 Subject: [PATCH 39/46] Reactive Solidifier --- pkg/protocol/engine/blockdag/blockdag.go | 3 - .../blockdag/inmemoryblockdag/blockdag.go | 92 +++++++------------ pkg/protocol/engine/blocks/block.go | 25 +++-- 3 files changed, 50 insertions(+), 70 deletions(-) diff --git a/pkg/protocol/engine/blockdag/blockdag.go b/pkg/protocol/engine/blockdag/blockdag.go index 9db7cd1aa..77b4164ee 100644 --- a/pkg/protocol/engine/blockdag/blockdag.go +++ b/pkg/protocol/engine/blockdag/blockdag.go @@ -16,8 +16,5 @@ type BlockDAG interface { // without requesting it. GetOrRequestBlock(blockID iotago.BlockID) (block *blocks.Block, requested bool) - // SetInvalid marks a Block as invalid. - SetInvalid(block *blocks.Block, reason error) (wasUpdated bool) - module.Interface } diff --git a/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go b/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go index eacda875a..12ce287ba 100644 --- a/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go +++ b/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go @@ -1,7 +1,8 @@ package inmemoryblockdag import ( - "github.com/iotaledger/hive.go/core/causalorder" + "sync/atomic" + "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/hive.go/runtime/module" @@ -26,9 +27,6 @@ type BlockDAG struct { // evictionState contains information about the current eviction state. evictionState *eviction.State - // solidifier contains the solidifier instance used to determine the solidity of Blocks. - solidifier *causalorder.CausalOrder[iotago.SlotIndex, iotago.BlockID, *blocks.Block] - latestCommitmentFunc func() *model.Commitment uncommittedSlotBlocks *buffer.UnsolidCommitmentBuffer[*blocks.Block] @@ -67,7 +65,7 @@ func NewProvider(opts ...options.Option[BlockDAG]) module.Provider[*engine.Engin defer b.solidifierMutex.RUnlock() for _, block := range unsolidBlocks { - b.solidifier.Queue(block) + b.setupBlock(block) } }, event.WithWorkerPool(wp)) @@ -83,6 +81,32 @@ func NewProvider(opts ...options.Option[BlockDAG]) module.Provider[*engine.Engin }) } +func (b *BlockDAG) setupBlock(block *blocks.Block) { + var unsolidParentsCount atomic.Int32 + unsolidParentsCount.Store(int32(len(block.Parents()))) + + block.ForEachParent(func(parent iotago.Parent) { + parentBlock, exists := b.blockCache.Block(parent.ID) + if !exists { + panic("cannot setup block without existing parent") + } + + parentBlock.Solid().OnUpdateOnce(func(_, _ bool) { + if unsolidParentsCount.Add(-1) == 0 { + if block.SetSolid() { + b.events.BlockSolid.Trigger(block) + } + } + }) + + parentBlock.Invalid().OnUpdateOnce(func(_, _ bool) { + if block.SetInvalid() { + b.events.BlockInvalid.Trigger(block, ierrors.Errorf("parent block %s is marked as invalid", parent.ID)) + } + }) + }) +} + // New is the constructor for the BlockDAG and creates a new BlockDAG instance. func New(workers *workerpool.Group, apiProvider iotago.APIProvider, evictionState *eviction.State, blockCache *blocks.Blocks, errorHandler func(error), opts ...options.Option[BlockDAG]) (newBlockDAG *BlockDAG) { return options.Apply(&BlockDAG{ @@ -94,23 +118,7 @@ func New(workers *workerpool.Group, apiProvider iotago.APIProvider, evictionStat workerPool: workers.CreatePool("Solidifier", 2), errorHandler: errorHandler, uncommittedSlotBlocks: buffer.NewUnsolidCommitmentBuffer[*blocks.Block](int(apiProvider.CurrentAPI().ProtocolParameters().MaxCommittableAge()) * 2), - }, opts, - func(b *BlockDAG) { - b.solidifier = causalorder.New( - b.workerPool, - blockCache.Block, - (*blocks.Block).IsSolid, - b.markSolid, - b.markInvalid, - (*blocks.Block).Parents, - causalorder.WithReferenceValidator[iotago.SlotIndex, iotago.BlockID](checkReference), - ) - - blockCache.Evict.Hook(b.evictSlot) - }, - (*BlockDAG).TriggerConstructed, - (*BlockDAG).TriggerInitialized, - ) + }, opts, (*BlockDAG).TriggerConstructed, (*BlockDAG).TriggerInitialized) } var _ blockdag.BlockDAG = new(BlockDAG) @@ -137,7 +145,7 @@ func (b *BlockDAG) Attach(data *model.Block) (block *blocks.Block, wasAttached b b.solidifierMutex.RLock() defer b.solidifierMutex.RUnlock() - b.solidifier.Queue(block) + b.setupBlock(block) } return @@ -155,15 +163,6 @@ func (b *BlockDAG) GetOrRequestBlock(blockID iotago.BlockID) (block *blocks.Bloc }) } -// SetInvalid marks a Block as invalid. -func (b *BlockDAG) SetInvalid(block *blocks.Block, reason error) (wasUpdated bool) { - if wasUpdated = block.SetInvalid(); wasUpdated { - b.events.BlockInvalid.Trigger(block, reason) - } - - return -} - func (b *BlockDAG) Shutdown() { b.TriggerStopped() b.workers.Shutdown() @@ -173,26 +172,6 @@ func (b *BlockDAG) setRetainBlockFailureFunc(retainBlockFailure func(blockID iot b.retainBlockFailure = retainBlockFailure } -// evictSlot is used to evict Blocks from committed slots from the BlockDAG. -func (b *BlockDAG) evictSlot(slot iotago.SlotIndex) { - b.solidifierMutex.Lock() - defer b.solidifierMutex.Unlock() - - b.solidifier.EvictUntil(slot) -} - -func (b *BlockDAG) markSolid(block *blocks.Block) (err error) { - if block.SetSolid() { - b.events.BlockSolid.Trigger(block) - } - - return nil -} - -func (b *BlockDAG) markInvalid(block *blocks.Block, reason error) { - b.SetInvalid(block, ierrors.Wrap(reason, "block marked as invalid in BlockDAG")) -} - // attach tries to attach the given Block to the BlockDAG. func (b *BlockDAG) attach(data *model.Block) (block *blocks.Block, wasAttached bool, err error) { shouldAttach, err := b.shouldAttach(data) @@ -265,12 +244,3 @@ func (b *BlockDAG) registerChild(child *blocks.Block, parent iotago.Parent) { parentBlock.AppendChild(child, parent.Type) } } - -// checkReference checks if the reference between the child and its parent is valid. -func checkReference(child *blocks.Block, parent *blocks.Block) (err error) { - if parent.IsInvalid() { - return ierrors.Errorf("parent %s of child %s is marked as invalid", parent.ID(), child.ID()) - } - - return nil -} diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index 87ba51bc8..3d66c168e 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -19,7 +19,7 @@ type Block struct { // BlockDAG block missing bool missingBlockID iotago.BlockID - solid bool + solid reactive.Variable[bool] invalid reactive.Variable[bool] strongChildren []*Block weakChildren []*Block @@ -82,6 +82,7 @@ func NewBlock(data *model.Block) *Block { acceptanceRatifiers: ds.NewSet[account.SeatIndex](), confirmationRatifiers: ds.NewSet[account.SeatIndex](), modelBlock: data, + solid: reactive.NewVariable[bool](), invalid: reactive.NewVariable[bool](), booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), @@ -103,7 +104,7 @@ func NewRootBlock(blockID iotago.BlockID, commitmentID iotago.CommitmentID, issu commitmentID: commitmentID, issuingTime: issuingTime, }, - solid: true, + solid: reactive.NewVariable[bool](), invalid: reactive.NewVariable[bool](), booked: reactive.NewVariable[bool](), preAccepted: true, @@ -113,6 +114,7 @@ func NewRootBlock(blockID iotago.BlockID, commitmentID iotago.CommitmentID, issu } // This should be true since we commit and evict on acceptance. + b.solid.Set(true) b.booked.Set(true) b.notarized.Set(true) b.accepted.Set(true) @@ -129,6 +131,7 @@ func NewMissingBlock(blockID iotago.BlockID) *Block { payloadConflictIDs: ds.NewSet[iotago.TransactionID](), acceptanceRatifiers: ds.NewSet[account.SeatIndex](), confirmationRatifiers: ds.NewSet[account.SeatIndex](), + solid: reactive.NewVariable[bool](), invalid: reactive.NewVariable[bool](), booked: reactive.NewVariable[bool](), accepted: reactive.NewVariable[bool](), @@ -255,12 +258,20 @@ func (b *Block) IsMissing() (isMissing bool) { return b.missing } +// Solid returns a reactive variable that is true if the Block is solid (the entire causal history is known). +func (b *Block) Solid() (solid reactive.Variable[bool]) { + b.mutex.RLock() + defer b.mutex.RUnlock() + + return b.solid +} + // IsSolid returns true if the Block is solid (the entire causal history is known). func (b *Block) IsSolid() (isSolid bool) { b.mutex.RLock() defer b.mutex.RUnlock() - return b.solid + return b.solid.Get() } // Invalid returns a reactive variable that is true if the Block was marked as invalid. @@ -324,11 +335,13 @@ func (b *Block) SetSolid() (wasUpdated bool) { b.mutex.Lock() defer b.mutex.Unlock() - if wasUpdated = !b.solid; wasUpdated { - b.solid = true + if b.solid.Get() { + return false } - return + b.solid.Set(true) + + return true } // SetInvalid marks the Block as invalid. From 0858b90e8e30adba68fe6db42c0772a6d6b520d6 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Fri, 6 Oct 2023 12:35:21 +0200 Subject: [PATCH 40/46] Handle booking error --- pkg/protocol/engine/booker/inmemorybooker/booker.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/protocol/engine/booker/inmemorybooker/booker.go b/pkg/protocol/engine/booker/inmemorybooker/booker.go index 5e67513ca..dacec7b53 100644 --- a/pkg/protocol/engine/booker/inmemorybooker/booker.go +++ b/pkg/protocol/engine/booker/inmemorybooker/booker.go @@ -134,7 +134,11 @@ func (b *Booker) setupBlock(block *blocks.Block) { parentBlock.Booked().OnUpdateOnce(func(_, _ bool) { if unbookedParentsCount.Add(-1) == 0 { - b.book(block) + if err := b.book(block); err != nil { + if block.SetInvalid() { + b.events.BlockInvalid.Trigger(block, ierrors.Wrap(err, "failed to book block")) + } + } } }) From 8f8f8de73ef95ec849eebabfdb5d01f72189dd69 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Fri, 6 Oct 2023 12:40:23 +0200 Subject: [PATCH 41/46] Remove unused workers --- .../engine/blockdag/inmemoryblockdag/blockdag.go | 5 +---- pkg/protocol/engine/booker/inmemorybooker/booker.go | 9 ++------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go b/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go index 12ce287ba..10784255e 100644 --- a/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go +++ b/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go @@ -36,9 +36,7 @@ type BlockDAG struct { solidifierMutex syncutils.RWMutex - workers *workerpool.Group - workerPool *workerpool.WorkerPool - + workers *workerpool.Group errorHandler func(error) apiProvider iotago.APIProvider @@ -115,7 +113,6 @@ func New(workers *workerpool.Group, apiProvider iotago.APIProvider, evictionStat evictionState: evictionState, blockCache: blockCache, workers: workers, - workerPool: workers.CreatePool("Solidifier", 2), errorHandler: errorHandler, uncommittedSlotBlocks: buffer.NewUnsolidCommitmentBuffer[*blocks.Block](int(apiProvider.CurrentAPI().ProtocolParameters().MaxCommittableAge()) * 2), }, opts, (*BlockDAG).TriggerConstructed, (*BlockDAG).TriggerInitialized) diff --git a/pkg/protocol/engine/booker/inmemorybooker/booker.go b/pkg/protocol/engine/booker/inmemorybooker/booker.go index dacec7b53..a1a6dfd0c 100644 --- a/pkg/protocol/engine/booker/inmemorybooker/booker.go +++ b/pkg/protocol/engine/booker/inmemorybooker/booker.go @@ -8,7 +8,6 @@ import ( "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/module" "github.com/iotaledger/hive.go/runtime/options" - "github.com/iotaledger/hive.go/runtime/workerpool" "github.com/iotaledger/iota-core/pkg/protocol/engine" "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" "github.com/iotaledger/iota-core/pkg/protocol/engine/booker" @@ -22,8 +21,6 @@ import ( type Booker struct { events *booker.Events - workers *workerpool.Group - blockCache *blocks.Blocks conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, mempool.StateID, ledger.BlockVoteRank] @@ -40,7 +37,7 @@ type Booker struct { func NewProvider(opts ...options.Option[Booker]) module.Provider[*engine.Engine, booker.Booker] { return module.Provide(func(e *engine.Engine) booker.Booker { - b := New(e.Workers.CreateGroup("Booker"), e, e.BlockCache, e.ErrorHandler("booker"), opts...) + b := New(e, e.BlockCache, e.ErrorHandler("booker"), opts...) e.HookConstructed(func() { b.ledger = e.Ledger b.ledger.HookConstructed(func() { @@ -70,13 +67,12 @@ func NewProvider(opts ...options.Option[Booker]) module.Provider[*engine.Engine, }) } -func New(workers *workerpool.Group, apiProvider iotago.APIProvider, blockCache *blocks.Blocks, errorHandler func(error), opts ...options.Option[Booker]) *Booker { +func New(apiProvider iotago.APIProvider, blockCache *blocks.Blocks, errorHandler func(error), opts ...options.Option[Booker]) *Booker { return options.Apply(&Booker{ events: booker.NewEvents(), apiProvider: apiProvider, blockCache: blockCache, - workers: workers, errorHandler: errorHandler, }, opts, (*Booker).TriggerConstructed) } @@ -119,7 +115,6 @@ func (b *Booker) Queue(block *blocks.Block) error { func (b *Booker) Shutdown() { b.TriggerStopped() - b.workers.Shutdown() } func (b *Booker) setupBlock(block *blocks.Block) { From a4f999c3faf18dec13e3ce524ce0c8779866745d Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Sat, 7 Oct 2023 10:17:17 +0200 Subject: [PATCH 42/46] Remove locks from reactive variables and simplify API --- pkg/protocol/engine/blocks/block.go | 57 ++++++++--------------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index 3d66c168e..d20e82e15 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -260,20 +260,19 @@ func (b *Block) IsMissing() (isMissing bool) { // Solid returns a reactive variable that is true if the Block is solid (the entire causal history is known). func (b *Block) Solid() (solid reactive.Variable[bool]) { - b.mutex.RLock() - defer b.mutex.RUnlock() - return b.solid } // IsSolid returns true if the Block is solid (the entire causal history is known). func (b *Block) IsSolid() (isSolid bool) { - b.mutex.RLock() - defer b.mutex.RUnlock() - return b.solid.Get() } +// SetSolid marks the Block as solid. +func (b *Block) SetSolid() (wasUpdated bool) { + return !b.solid.Set(true) +} + // Invalid returns a reactive variable that is true if the Block was marked as invalid. func (b *Block) Invalid() (invalid reactive.Variable[bool]) { return b.invalid @@ -281,12 +280,14 @@ func (b *Block) Invalid() (invalid reactive.Variable[bool]) { // IsInvalid returns true if the Block was marked as invalid. func (b *Block) IsInvalid() (isInvalid bool) { - b.mutex.RLock() - defer b.mutex.RUnlock() - return b.invalid.Get() } +// SetInvalid marks the Block as invalid. +func (b *Block) SetInvalid() (wasUpdated bool) { + return !b.invalid.Set(true) +} + // Children returns the children of the Block. func (b *Block) Children() (children []*Block) { b.mutex.RLock() @@ -330,34 +331,6 @@ func (b *Block) ShallowLikeChildren() []*Block { return lo.CopySlice(b.shallowLikeChildren) } -// SetSolid marks the Block as solid. -func (b *Block) SetSolid() (wasUpdated bool) { - b.mutex.Lock() - defer b.mutex.Unlock() - - if b.solid.Get() { - return false - } - - b.solid.Set(true) - - return true -} - -// SetInvalid marks the Block as invalid. -func (b *Block) SetInvalid() (wasUpdated bool) { - b.mutex.Lock() - defer b.mutex.Unlock() - - if b.invalid.Get() { - return false - } - - b.invalid.Set(true) - - return true -} - func (b *Block) AppendChild(child *Block, childType iotago.ParentsType) { b.mutex.Lock() defer b.mutex.Unlock() @@ -484,6 +457,11 @@ func (b *Block) AcceptanceRatifiers() []account.SeatIndex { return b.acceptanceRatifiers.ToSlice() } +// Accepted returns a reactive variable that is true if the Block was accepted. +func (b *Block) Accepted() reactive.Variable[bool] { + return b.accepted +} + // IsAccepted returns true if the Block was accepted. func (b *Block) IsAccepted() bool { return b.accepted.Get() @@ -494,11 +472,6 @@ func (b *Block) SetAccepted() (wasUpdated bool) { return !b.accepted.Set(true) } -// Accepted returns a reactive variable that is true if the Block was accepted. -func (b *Block) Accepted() reactive.Variable[bool] { - return b.accepted -} - // IsScheduled returns true if the Block was scheduled. func (b *Block) IsScheduled() bool { b.mutex.RLock() From a85cd2931060135c7eba8d1f2eefec87171f847c Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:42:33 +0200 Subject: [PATCH 43/46] Address review comments --- .../engine/blockdag/inmemoryblockdag/blockdag.go | 13 +------------ pkg/protocol/engine/booker/inmemorybooker/booker.go | 4 +++- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go b/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go index 10784255e..148bc88c6 100644 --- a/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go +++ b/pkg/protocol/engine/blockdag/inmemoryblockdag/blockdag.go @@ -7,7 +7,6 @@ import ( "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/hive.go/runtime/module" "github.com/iotaledger/hive.go/runtime/options" - "github.com/iotaledger/hive.go/runtime/syncutils" "github.com/iotaledger/hive.go/runtime/workerpool" "github.com/iotaledger/iota-core/pkg/core/buffer" "github.com/iotaledger/iota-core/pkg/model" @@ -34,8 +33,6 @@ type BlockDAG struct { blockCache *blocks.Blocks - solidifierMutex syncutils.RWMutex - workers *workerpool.Group errorHandler func(error) apiProvider iotago.APIProvider @@ -57,12 +54,7 @@ func NewProvider(opts ...options.Option[BlockDAG]) module.Provider[*engine.Engin }, event.WithWorkerPool(wp)) e.Events.Notarization.LatestCommitmentUpdated.Hook(func(commitment *model.Commitment) { - unsolidBlocks := b.uncommittedSlotBlocks.GetValuesAndEvict(commitment.ID()) - - b.solidifierMutex.RLock() - defer b.solidifierMutex.RUnlock() - - for _, block := range unsolidBlocks { + for _, block := range b.uncommittedSlotBlocks.GetValuesAndEvict(commitment.ID()) { b.setupBlock(block) } }, event.WithWorkerPool(wp)) @@ -139,9 +131,6 @@ func (b *BlockDAG) Attach(data *model.Block) (block *blocks.Block, wasAttached b return } - b.solidifierMutex.RLock() - defer b.solidifierMutex.RUnlock() - b.setupBlock(block) } diff --git a/pkg/protocol/engine/booker/inmemorybooker/booker.go b/pkg/protocol/engine/booker/inmemorybooker/booker.go index a1a6dfd0c..3d3be8df8 100644 --- a/pkg/protocol/engine/booker/inmemorybooker/booker.go +++ b/pkg/protocol/engine/booker/inmemorybooker/booker.go @@ -124,7 +124,9 @@ func (b *Booker) setupBlock(block *blocks.Block) { block.ForEachParent(func(parent iotago.Parent) { parentBlock, exists := b.blockCache.Block(parent.ID) if !exists { - panic("cannot setup block without existing parent") + b.errorHandler(ierrors.Errorf("cannot setup block %s without existing parent %s", block.ID(), parent.ID)) + + return } parentBlock.Booked().OnUpdateOnce(func(_, _ bool) { From 76c7979b1d80450b1c3fb8e67332b99917d4a6f7 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:30:48 +0200 Subject: [PATCH 44/46] Revert Docker preset to Now genesis time --- tools/genesis-snapshot/presets/presets.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/genesis-snapshot/presets/presets.go b/tools/genesis-snapshot/presets/presets.go index 01fa4bf6a..d6627393d 100644 --- a/tools/genesis-snapshot/presets/presets.go +++ b/tools/genesis-snapshot/presets/presets.go @@ -1,6 +1,8 @@ package presets import ( + "time" + "golang.org/x/crypto/blake2b" "github.com/iotaledger/hive.go/crypto/ed25519" @@ -94,7 +96,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ iotago.NewV3ProtocolParameters( iotago.WithNetworkOptions("docker", "rms"), iotago.WithSupplyOptions(10_000_000_000, 1, 1, 10, 100, 100, 100), - iotago.WithTimeProviderOptions(1696908344, 10, 13), + iotago.WithTimeProviderOptions(time.Now().Unix(), 10, 13), iotago.WithLivenessOptions(30, 30, 7, 14, 30), // increase/decrease threshold = fraction * slotDurationInSeconds * schedulerRate iotago.WithCongestionControlOptions(500, 500, 500, 800000, 500000, 100000, 1000, 100), From d037d34441acaed68b58b720e3cdc403e552ce73 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:37:33 +0200 Subject: [PATCH 45/46] Bump hive.go to get bug fixes --- go.mod | 26 +++++++++--------- go.sum | 52 +++++++++++++++++------------------ tools/evil-spammer/go.mod | 26 +++++++++--------- tools/evil-spammer/go.sum | 52 +++++++++++++++++------------------ tools/gendoc/go.mod | 26 +++++++++--------- tools/gendoc/go.sum | 52 +++++++++++++++++------------------ tools/genesis-snapshot/go.mod | 22 +++++++-------- tools/genesis-snapshot/go.sum | 44 ++++++++++++++--------------- 8 files changed, 150 insertions(+), 150 deletions(-) diff --git a/go.mod b/go.mod index 37dae713d..675c5d5ac 100644 --- a/go.mod +++ b/go.mod @@ -11,19 +11,19 @@ require ( github.com/google/uuid v1.3.1 github.com/gorilla/websocket v1.5.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab + github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217 github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231005191759-16a3636128c4 github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c diff --git a/go.sum b/go.sum index 563a6d695..8532876d3 100644 --- a/go.sum +++ b/go.sum @@ -275,32 +275,32 @@ github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJ github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 h1:dTrD7X2PTNgli6EbS4tV9qu3QAm/kBU3XaYZV2xdzys= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7/go.mod h1:ZRdPu684P0fQ1z8sXz4dj9H5LWHhz4a9oCtvjunkSrw= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab h1:3U1ADSPHU9GahpWujnkwOlGxA+NMl9l0j3ch4ISH1S0= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab h1:ePgcMl1XOXoF4kNfwMGn63GXZSihv+Z2t1GWLKqkGOw= -github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab h1:u7wN87wrmlPbUpNZhHfNKN6HLLQdY/zICIiJgVCSBvM= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab h1:u4h5GdvR1MTNZHYkLx8USCadbkMkISZyYXudH5qEhZQ= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab h1:0wGm1JPCBNK7h9WYtFZhSxmbhPmiBEzeeonUfJmVASE= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab h1:Wlv4bCfT6IZ3LD3jzHCgT00MdL0LR7kzhlW3zQohKKA= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab h1:RMKlQlTpWSSfauU3KgNyv/8WGzTTx3G4KzFuLf1EhrM= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab h1:50bOe5+XlIj0pPqcMNkOl+nf4BEITIhWuSr1j3fieLI= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab h1:o9JT//S67PRsrEir1GSdlNz2hLYfG+6SDayxmJm+jKQ= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab h1:AWU4PRv5No/ghKH02JY3/N9Xpv2he+byVLRd7DPHJGg= -github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab h1:ZE7MENkq9l8B+uIt1ulFfflDPnYX4Xxk6UYbzAPr8/U= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab h1:ebO3VhgcS2Dd8zBe+8Lizd8RoV00TUAm06tY0HGZmIE= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab h1:nDsUCc2/EPFspZcKk3T4HklhUeI+B5ed3W+HoTciYzA= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 h1:lbrYweNe+DB/kh7OYlogJMQfEDRpriyIgA+MmHmb01k= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5 h1:P2BE6RylO7mlEtJSbNyuRz6OcJTNs0MZ0qFIN5lI3Kg= +github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:q2H/9TE6hvg6TKZI0YoxtbCdrf8O1sYBVjNT2Y3yAIU= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 h1:AsgWEa8dpgF0JX3pc+nwaoQLlc5rKEoWAgrYdN1AIRE= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 h1:T/vnm1B2SFYWz7QiQsQq0AuoJCXKwW3hBCITudvh//c= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 h1:8TgnDcl6gIqXqgTnx4wA3LZt8vwAsVfekcKlPK5WRNY= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 h1:xyVUPe/tZtS3nkg8fU1GB1ZyUo7D32YfrY0XNA8GZhM= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 h1:Q8giZLqmIJRlcUS5x1TxVlS5X+iHgZ8zOq4GsK3YWnQ= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 h1:nI6LJ32saPs1c3HwA7V3T2jo3bh4+UuhBg1EsBK9N7k= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 h1:XVKwwjBJGOUuNzormIYJMWgqyscgusR5WtxA3rxql5g= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5 h1:hp+Bstpyxgeci0eDnEp0CZDbavgwnhDHkBTCf/fBQv4= +github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 h1:2TxlF+6APu1ZeImwny5EAwfe/n/JVlq+1NpzBybJnCU= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 h1:SV8s8rZIHj2yhGRj8vX2AyA3MOKOWPk4rKiz0mJ/4mw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 h1:zD60l2AnJmYLfjwhytAILQLZbkgmOPeg7IvFSY6Uv1E= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217 h1:DdrsW+J04ne2j6bjU1yVu+4C4CjpjGFYDEVMtmg0zyA= github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217/go.mod h1:OWZGwG4q2Ypd/D6LJicgdPXtw9yYkhaZEvJFhkIm2Ck= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231005191759-16a3636128c4 h1:uI+sZeZnGzAkM34JDbZBfyRIXrkkd1L0w8qVJ5rGy3E= diff --git a/tools/evil-spammer/go.mod b/tools/evil-spammer/go.mod index 6a1e0c8e3..2faecf860 100644 --- a/tools/evil-spammer/go.mod +++ b/tools/evil-spammer/go.mod @@ -8,13 +8,13 @@ replace github.com/iotaledger/iota-core/tools/genesis-snapshot => ../genesis-sna require ( github.com/AlecAivazis/survey/v2 v2.3.7 - github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab + github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota-core/tools/genesis-snapshot v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c @@ -37,12 +37,12 @@ require ( github.com/holiman/uint256 v1.2.3 // indirect github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 // indirect - github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab // indirect + github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect diff --git a/tools/evil-spammer/go.sum b/tools/evil-spammer/go.sum index ceb658824..d8913b4b2 100644 --- a/tools/evil-spammer/go.sum +++ b/tools/evil-spammer/go.sum @@ -169,32 +169,32 @@ github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJ github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 h1:dTrD7X2PTNgli6EbS4tV9qu3QAm/kBU3XaYZV2xdzys= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7/go.mod h1:ZRdPu684P0fQ1z8sXz4dj9H5LWHhz4a9oCtvjunkSrw= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab h1:3U1ADSPHU9GahpWujnkwOlGxA+NMl9l0j3ch4ISH1S0= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab h1:ePgcMl1XOXoF4kNfwMGn63GXZSihv+Z2t1GWLKqkGOw= -github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab h1:u7wN87wrmlPbUpNZhHfNKN6HLLQdY/zICIiJgVCSBvM= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab h1:u4h5GdvR1MTNZHYkLx8USCadbkMkISZyYXudH5qEhZQ= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab h1:0wGm1JPCBNK7h9WYtFZhSxmbhPmiBEzeeonUfJmVASE= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab h1:Wlv4bCfT6IZ3LD3jzHCgT00MdL0LR7kzhlW3zQohKKA= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab h1:RMKlQlTpWSSfauU3KgNyv/8WGzTTx3G4KzFuLf1EhrM= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab h1:50bOe5+XlIj0pPqcMNkOl+nf4BEITIhWuSr1j3fieLI= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab h1:o9JT//S67PRsrEir1GSdlNz2hLYfG+6SDayxmJm+jKQ= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab h1:AWU4PRv5No/ghKH02JY3/N9Xpv2he+byVLRd7DPHJGg= -github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab h1:ZE7MENkq9l8B+uIt1ulFfflDPnYX4Xxk6UYbzAPr8/U= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab h1:ebO3VhgcS2Dd8zBe+8Lizd8RoV00TUAm06tY0HGZmIE= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab h1:nDsUCc2/EPFspZcKk3T4HklhUeI+B5ed3W+HoTciYzA= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 h1:lbrYweNe+DB/kh7OYlogJMQfEDRpriyIgA+MmHmb01k= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5 h1:P2BE6RylO7mlEtJSbNyuRz6OcJTNs0MZ0qFIN5lI3Kg= +github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:q2H/9TE6hvg6TKZI0YoxtbCdrf8O1sYBVjNT2Y3yAIU= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 h1:AsgWEa8dpgF0JX3pc+nwaoQLlc5rKEoWAgrYdN1AIRE= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 h1:T/vnm1B2SFYWz7QiQsQq0AuoJCXKwW3hBCITudvh//c= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 h1:8TgnDcl6gIqXqgTnx4wA3LZt8vwAsVfekcKlPK5WRNY= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 h1:xyVUPe/tZtS3nkg8fU1GB1ZyUo7D32YfrY0XNA8GZhM= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 h1:Q8giZLqmIJRlcUS5x1TxVlS5X+iHgZ8zOq4GsK3YWnQ= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 h1:nI6LJ32saPs1c3HwA7V3T2jo3bh4+UuhBg1EsBK9N7k= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 h1:XVKwwjBJGOUuNzormIYJMWgqyscgusR5WtxA3rxql5g= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5 h1:hp+Bstpyxgeci0eDnEp0CZDbavgwnhDHkBTCf/fBQv4= +github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 h1:2TxlF+6APu1ZeImwny5EAwfe/n/JVlq+1NpzBybJnCU= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 h1:SV8s8rZIHj2yhGRj8vX2AyA3MOKOWPk4rKiz0mJ/4mw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 h1:zD60l2AnJmYLfjwhytAILQLZbkgmOPeg7IvFSY6Uv1E= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c h1:3gWmDG+XNtTcT4FxcID6hijCUVs3kRGhAfhdv3FiWJs= github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c/go.mod h1:l5yEhEf90+V0sv8kgWINTsM/O6W75bgEDHxWrIlC4AY= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/tools/gendoc/go.mod b/tools/gendoc/go.mod index 8ec310193..965ecacb8 100644 --- a/tools/gendoc/go.mod +++ b/tools/gendoc/go.mod @@ -5,7 +5,7 @@ go 1.21 replace github.com/iotaledger/iota-core => ../../ require ( - github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab + github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5 github.com/iotaledger/hive.go/apputils v0.0.0-20230829152614-7afc7a4d89b3 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 ) @@ -58,18 +58,18 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 // indirect - github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab // indirect + github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 // indirect github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217 // indirect github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231005191759-16a3636128c4 // indirect github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c // indirect diff --git a/tools/gendoc/go.sum b/tools/gendoc/go.sum index b5b81ca0c..5089d6d4b 100644 --- a/tools/gendoc/go.sum +++ b/tools/gendoc/go.sum @@ -279,34 +279,34 @@ github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJ github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 h1:dTrD7X2PTNgli6EbS4tV9qu3QAm/kBU3XaYZV2xdzys= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7/go.mod h1:ZRdPu684P0fQ1z8sXz4dj9H5LWHhz4a9oCtvjunkSrw= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab h1:3U1ADSPHU9GahpWujnkwOlGxA+NMl9l0j3ch4ISH1S0= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab h1:ePgcMl1XOXoF4kNfwMGn63GXZSihv+Z2t1GWLKqkGOw= -github.com/iotaledger/hive.go/app v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 h1:lbrYweNe+DB/kh7OYlogJMQfEDRpriyIgA+MmHmb01k= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5 h1:P2BE6RylO7mlEtJSbNyuRz6OcJTNs0MZ0qFIN5lI3Kg= +github.com/iotaledger/hive.go/app v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:q2H/9TE6hvg6TKZI0YoxtbCdrf8O1sYBVjNT2Y3yAIU= github.com/iotaledger/hive.go/apputils v0.0.0-20230829152614-7afc7a4d89b3 h1:4aVJTc0KS77uEw0Tny4r0n1ORwcbAQDECaCclgf/6lE= github.com/iotaledger/hive.go/apputils v0.0.0-20230829152614-7afc7a4d89b3/go.mod h1:TZeAqieDu+xDOZp2e9+S+8pZp1PrfgcwLUnxmd8IgLU= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab h1:u7wN87wrmlPbUpNZhHfNKN6HLLQdY/zICIiJgVCSBvM= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab h1:u4h5GdvR1MTNZHYkLx8USCadbkMkISZyYXudH5qEhZQ= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab h1:0wGm1JPCBNK7h9WYtFZhSxmbhPmiBEzeeonUfJmVASE= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab h1:Wlv4bCfT6IZ3LD3jzHCgT00MdL0LR7kzhlW3zQohKKA= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab h1:RMKlQlTpWSSfauU3KgNyv/8WGzTTx3G4KzFuLf1EhrM= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab h1:50bOe5+XlIj0pPqcMNkOl+nf4BEITIhWuSr1j3fieLI= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab h1:o9JT//S67PRsrEir1GSdlNz2hLYfG+6SDayxmJm+jKQ= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab h1:AWU4PRv5No/ghKH02JY3/N9Xpv2he+byVLRd7DPHJGg= -github.com/iotaledger/hive.go/logger v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab h1:ZE7MENkq9l8B+uIt1ulFfflDPnYX4Xxk6UYbzAPr8/U= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab h1:ebO3VhgcS2Dd8zBe+8Lizd8RoV00TUAm06tY0HGZmIE= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab h1:nDsUCc2/EPFspZcKk3T4HklhUeI+B5ed3W+HoTciYzA= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 h1:AsgWEa8dpgF0JX3pc+nwaoQLlc5rKEoWAgrYdN1AIRE= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 h1:T/vnm1B2SFYWz7QiQsQq0AuoJCXKwW3hBCITudvh//c= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 h1:8TgnDcl6gIqXqgTnx4wA3LZt8vwAsVfekcKlPK5WRNY= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 h1:xyVUPe/tZtS3nkg8fU1GB1ZyUo7D32YfrY0XNA8GZhM= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 h1:Q8giZLqmIJRlcUS5x1TxVlS5X+iHgZ8zOq4GsK3YWnQ= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 h1:nI6LJ32saPs1c3HwA7V3T2jo3bh4+UuhBg1EsBK9N7k= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 h1:XVKwwjBJGOUuNzormIYJMWgqyscgusR5WtxA3rxql5g= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5 h1:hp+Bstpyxgeci0eDnEp0CZDbavgwnhDHkBTCf/fBQv4= +github.com/iotaledger/hive.go/logger v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 h1:2TxlF+6APu1ZeImwny5EAwfe/n/JVlq+1NpzBybJnCU= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 h1:SV8s8rZIHj2yhGRj8vX2AyA3MOKOWPk4rKiz0mJ/4mw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 h1:zD60l2AnJmYLfjwhytAILQLZbkgmOPeg7IvFSY6Uv1E= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217 h1:DdrsW+J04ne2j6bjU1yVu+4C4CjpjGFYDEVMtmg0zyA= github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231005192108-08a985c2e217/go.mod h1:OWZGwG4q2Ypd/D6LJicgdPXtw9yYkhaZEvJFhkIm2Ck= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231005191759-16a3636128c4 h1:uI+sZeZnGzAkM34JDbZBfyRIXrkkd1L0w8qVJ5rGy3E= diff --git a/tools/genesis-snapshot/go.mod b/tools/genesis-snapshot/go.mod index d3f6d0384..573a5889e 100644 --- a/tools/genesis-snapshot/go.mod +++ b/tools/genesis-snapshot/go.mod @@ -5,10 +5,10 @@ go 1.21 replace github.com/iotaledger/iota-core => ../../ require ( - github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab - github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab + github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 + github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c github.com/mr-tron/base58 v1.2.0 @@ -27,13 +27,13 @@ require ( github.com/holiman/uint256 v1.2.3 // indirect github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 // indirect - github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab // indirect - github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab // indirect + github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 // indirect + github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/text v0.2.0 // indirect diff --git a/tools/genesis-snapshot/go.sum b/tools/genesis-snapshot/go.sum index eb342e3f0..bce198553 100644 --- a/tools/genesis-snapshot/go.sum +++ b/tools/genesis-snapshot/go.sum @@ -28,28 +28,28 @@ github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJ github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7 h1:dTrD7X2PTNgli6EbS4tV9qu3QAm/kBU3XaYZV2xdzys= github.com/iotaledger/grocksdb v1.7.5-0.20230220105546-5162e18885c7/go.mod h1:ZRdPu684P0fQ1z8sXz4dj9H5LWHhz4a9oCtvjunkSrw= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab h1:3U1ADSPHU9GahpWujnkwOlGxA+NMl9l0j3ch4ISH1S0= -github.com/iotaledger/hive.go/ads v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab h1:u7wN87wrmlPbUpNZhHfNKN6HLLQdY/zICIiJgVCSBvM= -github.com/iotaledger/hive.go/constraints v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab h1:u4h5GdvR1MTNZHYkLx8USCadbkMkISZyYXudH5qEhZQ= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010083704-a2a91fb9e0ab/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab h1:0wGm1JPCBNK7h9WYtFZhSxmbhPmiBEzeeonUfJmVASE= -github.com/iotaledger/hive.go/crypto v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab h1:Wlv4bCfT6IZ3LD3jzHCgT00MdL0LR7kzhlW3zQohKKA= -github.com/iotaledger/hive.go/ds v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab h1:RMKlQlTpWSSfauU3KgNyv/8WGzTTx3G4KzFuLf1EhrM= -github.com/iotaledger/hive.go/ierrors v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab h1:50bOe5+XlIj0pPqcMNkOl+nf4BEITIhWuSr1j3fieLI= -github.com/iotaledger/hive.go/kvstore v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab h1:o9JT//S67PRsrEir1GSdlNz2hLYfG+6SDayxmJm+jKQ= -github.com/iotaledger/hive.go/lo v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab h1:ZE7MENkq9l8B+uIt1ulFfflDPnYX4Xxk6UYbzAPr8/U= -github.com/iotaledger/hive.go/runtime v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab h1:ebO3VhgcS2Dd8zBe+8Lizd8RoV00TUAm06tY0HGZmIE= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010083704-a2a91fb9e0ab/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab h1:nDsUCc2/EPFspZcKk3T4HklhUeI+B5ed3W+HoTciYzA= -github.com/iotaledger/hive.go/stringify v0.0.0-20231010083704-a2a91fb9e0ab/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5 h1:lbrYweNe+DB/kh7OYlogJMQfEDRpriyIgA+MmHmb01k= +github.com/iotaledger/hive.go/ads v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5 h1:AsgWEa8dpgF0JX3pc+nwaoQLlc5rKEoWAgrYdN1AIRE= +github.com/iotaledger/hive.go/constraints v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5 h1:T/vnm1B2SFYWz7QiQsQq0AuoJCXKwW3hBCITudvh//c= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231010121205-23c1f3fcddd5/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5 h1:8TgnDcl6gIqXqgTnx4wA3LZt8vwAsVfekcKlPK5WRNY= +github.com/iotaledger/hive.go/crypto v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5 h1:xyVUPe/tZtS3nkg8fU1GB1ZyUo7D32YfrY0XNA8GZhM= +github.com/iotaledger/hive.go/ds v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5 h1:Q8giZLqmIJRlcUS5x1TxVlS5X+iHgZ8zOq4GsK3YWnQ= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5 h1:nI6LJ32saPs1c3HwA7V3T2jo3bh4+UuhBg1EsBK9N7k= +github.com/iotaledger/hive.go/kvstore v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5 h1:XVKwwjBJGOUuNzormIYJMWgqyscgusR5WtxA3rxql5g= +github.com/iotaledger/hive.go/lo v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5 h1:2TxlF+6APu1ZeImwny5EAwfe/n/JVlq+1NpzBybJnCU= +github.com/iotaledger/hive.go/runtime v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5 h1:SV8s8rZIHj2yhGRj8vX2AyA3MOKOWPk4rKiz0mJ/4mw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231010121205-23c1f3fcddd5/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5 h1:zD60l2AnJmYLfjwhytAILQLZbkgmOPeg7IvFSY6Uv1E= +github.com/iotaledger/hive.go/stringify v0.0.0-20231010121205-23c1f3fcddd5/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c h1:3gWmDG+XNtTcT4FxcID6hijCUVs3kRGhAfhdv3FiWJs= github.com/iotaledger/iota.go/v4 v4.0.0-20231005184534-62e6761a7b7c/go.mod h1:l5yEhEf90+V0sv8kgWINTsM/O6W75bgEDHxWrIlC4AY= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= From 10de79e320279f5e64d2884babd8f67dd25c59e1 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:37:45 +0200 Subject: [PATCH 46/46] Fix Block's String method --- pkg/protocol/engine/blocks/block.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index d20e82e15..33de43b2e 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -623,8 +623,8 @@ func (b *Block) String() string { builder := stringify.NewStructBuilder("Engine.Block", stringify.NewStructField("id", b.id())) builder.AddField(stringify.NewStructField("Missing", b.missing)) - builder.AddField(stringify.NewStructField("Solid", b.solid)) - builder.AddField(stringify.NewStructField("Invalid", b.invalid)) + builder.AddField(stringify.NewStructField("Solid", b.solid.Get())) + builder.AddField(stringify.NewStructField("Invalid", b.invalid.Get())) builder.AddField(stringify.NewStructField("Booked", b.booked.Get())) builder.AddField(stringify.NewStructField("Witnesses", b.witnesses)) builder.AddField(stringify.NewStructField("PreAccepted", b.preAccepted))