diff --git a/components/dashboard/explorer_routes.go b/components/dashboard/explorer_routes.go index 21770ac50..703e8db62 100644 --- a/components/dashboard/explorer_routes.go +++ b/components/dashboard/explorer_routes.go @@ -132,8 +132,8 @@ func createExplorerBlock(block *model.Block, cachedBlock *blocks.Block, metadata return iotago.PayloadType(0) }(), Payload: func() json.RawMessage { - if isBasic && basicBlock.Payload != nil && basicBlock.Payload.PayloadType() == iotago.PayloadTransaction { - tx, _ := basicBlock.Payload.(*iotago.Transaction) + if isBasic && basicBlock.Payload != nil && basicBlock.Payload.PayloadType() == iotago.PayloadSignedTransaction { + tx, _ := basicBlock.Payload.(*iotago.SignedTransaction) txResponse := NewTransaction(tx) bytes, _ := json.Marshal(txResponse) @@ -143,8 +143,8 @@ func createExplorerBlock(block *model.Block, cachedBlock *blocks.Block, metadata return payloadJSON }(), TransactionID: func() string { - if isBasic && basicBlock.Payload != nil && basicBlock.Payload.PayloadType() == iotago.PayloadTransaction { - tx, _ := basicBlock.Payload.(*iotago.Transaction) + if isBasic && basicBlock.Payload != nil && basicBlock.Payload.PayloadType() == iotago.PayloadSignedTransaction { + tx, _ := basicBlock.Payload.(*iotago.SignedTransaction) id, _ := tx.ID() return id.ToHex() @@ -211,9 +211,9 @@ func getTransaction(c echo.Context) error { return ierrors.Errorf("block not found: %s", output.BlockID().ToHex()) } - iotaTX, isTX := block.Transaction() + iotaTX, isTX := block.SignedTransaction() if !isTX { - return ierrors.Errorf("payload is not a transaction: %s", output.BlockID().ToHex()) + return ierrors.Errorf("payload is not a signed transaction: %s", output.BlockID().ToHex()) } return httpserver.JSONResponse(c, http.StatusOK, NewTransaction(iotaTX)) diff --git a/components/dashboard/jsonresponse.go b/components/dashboard/jsonresponse.go index 93e33011b..4819642b6 100644 --- a/components/dashboard/jsonresponse.go +++ b/components/dashboard/jsonresponse.go @@ -116,7 +116,7 @@ func NewOutputID(outputID iotago.OutputID) *OutputID { // region Transaction ////////////////////////////////////////////////////////////////////////////////////////////////// -// Transaction represents the JSON model of a ledgerstate.Transaction. +// Transaction represents the JSON model of a iotago.SignedTransaction. type Transaction struct { TransactionID string `json:"txId"` NetworkID iotago.NetworkID `json:"networkId"` @@ -128,20 +128,20 @@ type Transaction struct { Payload []byte `json:"payload"` } -// NewTransaction returns a Transaction from the given ledgerstate.Transaction. -func NewTransaction(iotaTx *iotago.Transaction) *Transaction { - txID, err := iotaTx.ID() +// NewTransaction returns a Transaction from the given iotago.SignedTransaction. +func NewTransaction(signedTx *iotago.SignedTransaction) *Transaction { + txID, err := signedTx.ID() if err != nil { return nil } - inputs := make([]*Input, len(iotaTx.Essence.Inputs)) - for i, input := range iotaTx.Essence.Inputs { + inputs := make([]*Input, len(signedTx.Transaction.Inputs)) + for i, input := range signedTx.Transaction.Inputs { inputs[i] = NewInput(input) } - outputs := make([]*Output, len(iotaTx.Essence.Outputs)) - for i, output := range iotaTx.Essence.Outputs { + outputs := make([]*Output, len(signedTx.Transaction.Outputs)) + for i, output := range signedTx.Transaction.Outputs { outputs[i] = NewOutput(output) outputs[i].OutputID = &OutputID{ Hex: iotago.OutputIDFromTransactionIDAndIndex(txID, uint16(i)).ToHex(), @@ -150,19 +150,19 @@ func NewTransaction(iotaTx *iotago.Transaction) *Transaction { } } - unlockBlocks := make([]*UnlockBlock, len(iotaTx.Unlocks)) - for i, unlockBlock := range iotaTx.Unlocks { + unlockBlocks := make([]*UnlockBlock, len(signedTx.Unlocks)) + for i, unlockBlock := range signedTx.Unlocks { unlockBlocks[i] = NewUnlockBlock(unlockBlock) } dataPayload := make([]byte, 0) - if iotaTx.Essence.Payload != nil { - dataPayload, _ = deps.Protocol.CurrentAPI().Encode(iotaTx.Essence.Payload) + if signedTx.Transaction.Payload != nil { + dataPayload, _ = deps.Protocol.CurrentAPI().Encode(signedTx.Transaction.Payload) } return &Transaction{ - NetworkID: iotaTx.Essence.NetworkID, - CreationSlot: iotaTx.Essence.CreationSlot, + NetworkID: signedTx.Transaction.NetworkID, + CreationSlot: signedTx.Transaction.CreationSlot, Inputs: inputs, Outputs: outputs, Unlocks: unlockBlocks, @@ -174,7 +174,7 @@ func NewTransaction(iotaTx *iotago.Transaction) *Transaction { // region Input //////////////////////////////////////////////////////////////////////////////////////////////////////// -// Input represents the JSON model of a ledgerstate.Input. +// Input represents the JSON model of a iotago.Input. type Input struct { Type string `json:"type"` ReferencedOutputID *OutputID `json:"referencedOutputID,omitempty"` @@ -182,7 +182,7 @@ type Input struct { Output *Output `json:"output,omitempty"` } -// NewInput returns an Input from the given ledgerstate.Input. +// NewInput returns an Input from the given iotago.Input. func NewInput(input iotago.Input) *Input { utxoInput, isUtxoInput := input.(*iotago.UTXOInput) if !isUtxoInput { @@ -199,14 +199,14 @@ func NewInput(input iotago.Input) *Input { // region UnlockBlock ////////////////////////////////////////////////////////////////////////////////////////////////// -// UnlockBlock represents the JSON model of a ledgerstate.UnlockBlock. +// UnlockBlock represents the JSON model of a iotago.UnlockBlock. type UnlockBlock struct { Type string `json:"type"` SignatureType iotago.SignatureType `json:"signatureType,omitempty"` Signature json.RawMessage `json:"signature,omitempty"` } -// NewUnlockBlock returns an UnlockBlock from the given ledgerstate.UnlockBlock. +// NewUnlockBlock returns an UnlockBlock from the given UnlockBlock. func NewUnlockBlock(unlockBlock iotago.Unlock) *UnlockBlock { result := &UnlockBlock{ Type: unlockBlock.Type().String(), diff --git a/components/dashboard/visualizer.go b/components/dashboard/visualizer.go index f1b962f54..d9daffca2 100644 --- a/components/dashboard/visualizer.go +++ b/components/dashboard/visualizer.go @@ -43,7 +43,7 @@ type tipinfo struct { func sendVertex(blk *blocks.Block, confirmed bool) { modelBlk, _ := model.BlockFromBlock(blk.ProtocolBlock()) - tx, isTx := modelBlk.Transaction() + tx, isTx := modelBlk.SignedTransaction() broadcastWsBlock(&wsblk{MsgTypeVertex, &vertex{ ID: blk.ID().ToHex(), @@ -85,7 +85,7 @@ func runVisualizer(component *app.Component) { deps.Protocol.Events.Engine.BlockDAG.BlockAttached.Hook(func(block *blocks.Block) { sendVertex(block, false) - tx, hasTx := block.Transaction() + tx, hasTx := block.SignedTransaction() if hasTx { txMetadata, exists := deps.Protocol.MainEngineInstance().Ledger.MemPool().TransactionMetadata(lo.PanicOnErr(tx.ID())) if exists { diff --git a/components/inx/server_blocks.go b/components/inx/server_blocks.go index 79df07e55..e41439fbb 100644 --- a/components/inx/server_blocks.go +++ b/components/inx/server_blocks.go @@ -10,7 +10,6 @@ import ( "github.com/iotaledger/hive.go/runtime/contextutils" "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/hive.go/runtime/workerpool" - "github.com/iotaledger/hive.go/serializer/v2/serix" inx "github.com/iotaledger/inx/go" "github.com/iotaledger/iota-core/pkg/blockfactory" "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" @@ -119,17 +118,7 @@ func (s *Server) ListenToConfirmedBlocks(_ *inx.NoParams, srv inx.INX_ListenToCo } func (s *Server) SubmitBlock(ctx context.Context, rawBlock *inx.RawBlock) (*inx.BlockId, error) { - version, _, err := iotago.VersionFromBytes(rawBlock.GetData()) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "failed to parse block version: %s", err.Error()) - } - - apiForVersion, err := deps.Protocol.APIForVersion(version) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "invalid block version: %s", err.Error()) - } - - block, err := rawBlock.UnwrapBlock(apiForVersion, serix.WithValidation()) + block, err := rawBlock.UnwrapBlock(deps.Protocol) if err != nil { return nil, err } @@ -137,23 +126,6 @@ func (s *Server) SubmitBlock(ctx context.Context, rawBlock *inx.RawBlock) (*inx. return s.attachBlock(ctx, block) } -func (s *Server) SubmitPayload(ctx context.Context, rawPayload *inx.RawPayload) (*inx.BlockId, error) { - payload, err := rawPayload.Unwrap(deps.Protocol.CurrentAPI(), serix.WithValidation()) - if err != nil { - return nil, err - } - - mergedCtx, mergedCtxCancel := contextutils.MergeContexts(ctx, Component.Daemon().ContextStopped()) - defer mergedCtxCancel() - - block, err := deps.BlockIssuer.CreateBlock(mergedCtx, blockIssuerAccount, blockfactory.WithPayload(payload)) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "failed to create block: %s", err.Error()) - } - - return s.attachBlock(ctx, block.ProtocolBlock()) -} - func (s *Server) attachBlock(ctx context.Context, block *iotago.ProtocolBlock) (*inx.BlockId, error) { mergedCtx, mergedCtxCancel := contextutils.MergeContexts(ctx, Component.Daemon().ContextStopped()) defer mergedCtxCancel() diff --git a/components/inx/server_tips.go b/components/inx/server_tips.go new file mode 100644 index 000000000..ee107263f --- /dev/null +++ b/components/inx/server_tips.go @@ -0,0 +1,18 @@ +package inx + +import ( + "context" + + inx "github.com/iotaledger/inx/go" + iotago "github.com/iotaledger/iota.go/v4" +) + +func (s *Server) RequestTips(_ context.Context, req *inx.TipsRequest) (*inx.TipsResponse, error) { + references := deps.Protocol.MainEngineInstance().TipSelection.SelectTips(int(req.GetCount())) + + return &inx.TipsResponse{ + StrongTips: inx.NewBlockIds(references[iotago.StrongParentType]), + WeakTips: inx.NewBlockIds(references[iotago.WeakParentType]), + ShallowLikeTips: inx.NewBlockIds(references[iotago.ShallowLikeParentType]), + }, nil +} diff --git a/go.mod b/go.mod index a4595a568..2c22b2149 100644 --- a/go.mod +++ b/go.mod @@ -11,23 +11,22 @@ 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-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927112840-e982cb6707c9 - github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230925152824-4bfa09b8c132 - github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f + github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 + 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-20230929090257-1620d009ba8c 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 45547d315..49a8b5b59 100644 --- a/go.sum +++ b/go.sum @@ -275,40 +275,38 @@ 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-20230927122328-da2eaee8d805 h1:OtCoTjJlQeICgv+MitK/okK9TldywK7jue8jI8k78eg= -github.com/iotaledger/hive.go/ads v0.0.0-20230927122328-da2eaee8d805/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805 h1:9JZsyrQHMWoaDmcw5ssgQn8YMFix2cOE36ha7DGhY2A= -github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 h1:2vSacMbBgQSAD+sNptWJQrJchIS+j9gEABYSYlUulg0= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 h1:vfY5UFZeybxNTB5NYJAcQxxngSmnWMkemB5C6KKcG+Y= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 h1:teasrvb1DqJqOcVAxH15ZdGIPdNHI+lCU9OOrPBfHVc= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 h1:pj5K1GCyW8ugsL8QXHGkNmWEucoY3yJC/W5uBwxXEvQ= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 h1:heT6TrgjINpwnmUMo7uDJ5vdEpuStDIbDWcCdbTl6+I= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 h1:aFd/nvj8qkO+6qwaaUFwbfD4z9LhHZiDMFKzAzEZaE0= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 h1:aeJ/8Q6qw1fC6Mf3SGLwDwy2ZWVdG4q/9zNbKElVXmU= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 h1:i4DN1/Pbzd/QhbGddRPO8N18ZwrB7yzkFLHjgx1unk8= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805/go.mod h1:UF7PzlWdZ2H0Hkxrt4AgJmNVeMXUJzw4RwbHpib1DB0= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 h1:35L6o/GmpOy8GrcsnNSvBR1/Cqzt60Qt/4DniPCOOZY= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 h1:9UoQ4V2NxrUHT4m+LL1/PmexuZYpelDlaLBEimO5w+k= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 h1:2ls3eCyGrHaHEYMxKsdd6S5pmjAzwUrOG2G5O4dsJp0= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 h1:dXXdK66EE7/2/lgfmwU0J+avEYLryKe0Kpn63Kmn+xo= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927112840-e982cb6707c9 h1:vRGNfCcC7xwqQP0WKNQrtfBarx4y3tTnpfljmgOTMG4= -github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927112840-e982cb6707c9/go.mod h1:KbmEuxbhax3fyVrxF4RjBD1/MWLFxHLNDFBnDYUzok4= -github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230925152824-4bfa09b8c132 h1:YHvgNY3/TRx84UxqizkFe7vVUxAMQB2DOuEL8wjHxpg= -github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230925152824-4bfa09b8c132/go.mod h1:DIFr5lt73HLIyn/Lg2jtzfakwhIT0mMZjMFFji3GXeI= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f h1:b7mr4pVMRsqp4BMXFA6GR911t/10AmvZIjsvgLJegRQ= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 h1:HHxgNhbtD6WDCwSQBbPrQe8c4ZNjNi0KcgCJo0nm9bY= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729 h1:rBADf+IZDKkDOuZznwIdonxF9jcOSQJU/qOYSNInX84= +github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 h1:PQ9TFyXBrV6LLTOzE43CV/vz+ItN5v6lcA7ms0YOvcE= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 h1:mwIZhduBiOD4rG4hqrPhW616EU1wX4eD2zHu26be5Yc= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 h1:FpFlPNOHcvHDyk1gN3OuL/hgvTKVsc5IN+q8U1YF9P4= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 h1:hHdIZn95+HdP1JdjV8TAsuL5kU4eb4gncehyjXo/feQ= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 h1:+/OtOAx2tMy8ER3XBt9RpnspWyDrVqW6kQGAd24jT0k= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 h1:XCYvP8XwETTXF5LNz8q9X3EajDut7+UwTwqJ2TQ0TJo= +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-20230928074706-d58e32f86729 h1:hW4r9no+03ufp2fyx4IjTFwINkEz3OI3LqvSjv7SJ1c= +github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729 h1:FOQetJY2scpCtCGrZQWGw3RwB3lRIDdyu+M6P1NACM4= +github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 h1:4aRR9UG4dHpdlTcMN1Px++eaxlGXXk1n6co8t/WlchM= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 h1:mPmP3/0XJAf0ZkCzQenpoQPMv+m56Z8+A1i/UO18Hdw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 h1:gZlIK1OzdA3aZ78PsiWe3poVzawyw4S3zboMHE1TrY0= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182 h1:lQiktl3Q0B+cHbVum7WzJikOEP+buw686oSrw5Unyz8= +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-20230929090257-1620d009ba8c h1:faTwv2r4EZ6FixcFtaSD5M02YRm+/kmQKsLBsYSJl3I= +github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= 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/blockissuer.go b/pkg/blockfactory/blockissuer.go index c69ca9c6d..eb1692261 100644 --- a/pkg/blockfactory/blockissuer.go +++ b/pkg/blockfactory/blockissuer.go @@ -200,7 +200,7 @@ func (i *BlockIssuer) CreateBlock(ctx context.Context, issuerAccount Account, op } // only set the burned Mana as the last step before signing, so workscore calculation is correct. - blockBuilder.BurnedMana(rmc) + blockBuilder.MaxBurnedMana(rmc) blockBuilder.Sign(issuerAccount.ID(), issuerAccount.PrivateKey()) @@ -292,9 +292,9 @@ func (i *BlockIssuer) AttachBlock(ctx context.Context, iotaBlock *iotago.Protoco switch innerBlock := iotaBlock.Block.(type) { case *iotago.BasicBlock: switch payload := innerBlock.Payload.(type) { - case *iotago.Transaction: - if payload.Essence.NetworkID != protoParams.NetworkID() { - return iotago.EmptyBlockID(), ierrors.Wrapf(ErrBlockAttacherInvalidBlock, "invalid payload, error: wrong networkID: %d", payload.Essence.NetworkID) + case *iotago.SignedTransaction: + if payload.Transaction.NetworkID != protoParams.NetworkID() { + return iotago.EmptyBlockID(), ierrors.Wrapf(ErrBlockAttacherInvalidBlock, "invalid payload, error: wrong networkID: %d", payload.Transaction.NetworkID) } } @@ -330,7 +330,7 @@ func (i *BlockIssuer) AttachBlock(ctx context.Context, iotaBlock *iotago.Protoco return iotago.EmptyBlockID(), ierrors.Wrapf(ErrBlockAttacherAttachingNotPossible, "invalid block references, error: %w", err) } - if basicBlock, isBasicBlock := iotaBlock.Block.(*iotago.BasicBlock); isBasicBlock && basicBlock.BurnedMana == 0 { + if basicBlock, isBasicBlock := iotaBlock.Block.(*iotago.BasicBlock); isBasicBlock && basicBlock.MaxBurnedMana == 0 { rmcSlot, err := safemath.SafeSub(apiForVesion.TimeProvider().SlotFromTime(iotaBlock.IssuingTime), apiForVesion.ProtocolParameters().MaxCommittableAge()) if err != nil { rmcSlot = 0 @@ -341,7 +341,7 @@ func (i *BlockIssuer) AttachBlock(ctx context.Context, iotaBlock *iotago.Protoco } // only set the burned Mana as the last step before signing, so workscore calculation is correct. - basicBlock.BurnedMana, err = basicBlock.ManaCost(rmc, apiForVesion.ProtocolParameters().WorkScoreStructure()) + basicBlock.MaxBurnedMana, err = basicBlock.ManaCost(rmc, apiForVesion.ProtocolParameters().WorkScoreStructure()) if err != nil { return iotago.EmptyBlockID(), ierrors.Wrapf(err, "could not calculate Mana cost for block") } diff --git a/pkg/model/account_diff.go b/pkg/model/account_diff.go index 0846247fe..fadef8c74 100644 --- a/pkg/model/account_diff.go +++ b/pkg/model/account_diff.go @@ -2,13 +2,15 @@ package model import ( "bytes" + "context" "encoding/binary" "io" - "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/lo" + "github.com/iotaledger/hive.go/serializer/v2" "github.com/iotaledger/hive.go/serializer/v2/marshalutil" + "github.com/iotaledger/hive.go/serializer/v2/stream" iotago "github.com/iotaledger/iota.go/v4" ) @@ -67,13 +69,12 @@ func (d AccountDiff) Bytes() ([]byte, error) { m.WriteUint32(uint32(d.PreviousExpirySlot)) m.WriteBytes(lo.PanicOnErr(d.NewOutputID.Bytes())) m.WriteBytes(lo.PanicOnErr(d.PreviousOutputID.Bytes())) - m.WriteUint8(uint8(len(d.BlockIssuerKeysAdded))) - for _, blockIssuerKey := range d.BlockIssuerKeysAdded { - m.WriteBytes(blockIssuerKey.Bytes()) + + if err := writeBlockIssuerKeys(m, d.BlockIssuerKeysAdded); err != nil { + return nil, err } - m.WriteUint8(uint8(len(d.BlockIssuerKeysRemoved))) - for _, blockIssuerKey := range d.BlockIssuerKeysRemoved { - m.WriteBytes(blockIssuerKey.Bytes()) + if err := writeBlockIssuerKeys(m, d.BlockIssuerKeysRemoved); err != nil { + return nil, err } m.WriteInt64(d.ValidatorStakeChange) @@ -154,7 +155,7 @@ func (d *AccountDiff) readFromReadSeeker(reader io.ReadSeeker) (offset int, err keysRemoved, bytesRead, err := readBlockIssuerKeys(reader) if err != nil { - return offset, ierrors.Wrap(err, "unable to read removed blockIssuerKey in the diff") + return offset, ierrors.Wrap(err, "unable to read removed blockIssuerKeys in the diff") } offset += bytesRead @@ -203,60 +204,33 @@ func (d *AccountDiff) readFromReadSeeker(reader io.ReadSeeker) (offset int, err return offset, nil } +func writeBlockIssuerKeys(m *marshalutil.MarshalUtil, blockIssuerKeys iotago.BlockIssuerKeys) error { + blockIssuerKeysBytes, err := iotago.CommonSerixAPI().Encode(context.TODO(), blockIssuerKeys) + if err != nil { + return ierrors.Wrap(err, "unable to encode blockIssuerKeys in the diff") + } + + m.WriteUint64(uint64(len(blockIssuerKeysBytes))) + m.WriteBytes(blockIssuerKeysBytes) + + return nil +} + func readBlockIssuerKeys(reader io.ReadSeeker) (iotago.BlockIssuerKeys, int, error) { var bytesConsumed int - var blockIssuerKeysCount uint8 - if err := binary.Read(reader, binary.LittleEndian, &blockIssuerKeysCount); err != nil { - return nil, bytesConsumed, ierrors.Wrap(err, "unable to read blockIssuerKeys length in the diff") + blockIssuerKeysBytes, err := stream.ReadBlob(reader) + if err != nil { + return nil, bytesConsumed, ierrors.Wrap(err, "unable to read blockIssuerKeysBytes in the diff") } - bytesConsumed++ - blockIssuerKeys := iotago.NewBlockIssuerKeys() - for k := uint8(0); k < blockIssuerKeysCount; k++ { - blockIssuerKey, bytesRead, err := readBlockIssuerKey(reader) - if err != nil { - return nil, bytesConsumed, err - } - bytesConsumed += bytesRead + bytesConsumed += serializer.UInt64ByteSize // add the blob size + bytesConsumed += len(blockIssuerKeysBytes) - blockIssuerKeys.Add(blockIssuerKey) + var blockIssuerKeys iotago.BlockIssuerKeys + if _, err := iotago.CommonSerixAPI().Decode(context.TODO(), blockIssuerKeysBytes, &blockIssuerKeys); err != nil { + return nil, bytesConsumed, ierrors.Wrap(err, "unable to decode blockIssuerKeys in the diff") } return blockIssuerKeys, bytesConsumed, nil } - -func readBlockIssuerKey(reader io.ReadSeeker) (iotago.BlockIssuerKey, int, error) { - bytesConsumed := 0 - var blockIssuerKeyType iotago.BlockIssuerKeyType - if err := binary.Read(reader, binary.LittleEndian, &blockIssuerKeyType); err != nil { - return nil, bytesConsumed, ierrors.Wrapf(err, "unable to read block issuer key type in account diff") - } - bytesConsumed++ - - switch blockIssuerKeyType { - case iotago.BlockIssuerKeyEd25519PublicKey: - var ed25519PublicKey ed25519.PublicKey - var bytesRead, err = io.ReadFull(reader, ed25519PublicKey[:]) - bytesConsumed += bytesRead - if err != nil { - return nil, bytesConsumed, ierrors.Errorf("unable to read ed25519 public key in account diff: %w", err) - } - - return iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519PublicKey), bytesConsumed, nil - - // TODO: we need to add this case - //case iotago.BlockIssuerKeyEd25519Address: - // var ed25519Address *iotago.ImplicitAccountCreationAddress - // var bytesRead, err = io.ReadFull(reader, ed25519Address[:]) - // bytesConsumed += bytesRead - // if err != nil { - // return nil, bytesConsumed, ierrors.Errorf("unable to read ed25519 address key in account diff: %w", err) - // } - // - // return iotago.Ed25519AddressBlockIssuerKeyFromAddress(ed25519Address), bytesConsumed, nil - - default: - return nil, bytesConsumed, ierrors.Errorf("unsupported block issuer key type %d in account diff", blockIssuerKeyType) - } -} diff --git a/pkg/model/block.go b/pkg/model/block.go index bc5e604fd..557f715d0 100644 --- a/pkg/model/block.go +++ b/pkg/model/block.go @@ -83,13 +83,13 @@ func (blk *Block) Payload() iotago.Payload { return basicBlock.Payload } -func (blk *Block) Transaction() (tx *iotago.Transaction, isTransaction bool) { +func (blk *Block) SignedTransaction() (tx *iotago.SignedTransaction, isTransaction bool) { payload := blk.Payload() if payload == nil { return nil, false } - tx, isTransaction = payload.(*iotago.Transaction) + tx, isTransaction = payload.(*iotago.SignedTransaction) return tx, isTransaction } diff --git a/pkg/protocol/engine/accounts/accounts.go b/pkg/protocol/engine/accounts/accounts.go index ee191d652..403f569c0 100644 --- a/pkg/protocol/engine/accounts/accounts.go +++ b/pkg/protocol/engine/accounts/accounts.go @@ -141,6 +141,14 @@ func (a *AccountData) readFromReadSeeker(reader io.ReadSeeker) (int, error) { } bytesConsumed += bytesRead a.BlockIssuerKeys.Add(iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519PublicKey)) + case iotago.BlockIssuerKeyPublicKeyHash: + var implicitAccountCreationAddress iotago.ImplicitAccountCreationAddress + bytesRead, err = io.ReadFull(reader, implicitAccountCreationAddress[:]) + if err != nil { + return bytesConsumed, ierrors.Wrapf(err, "unable to read address %d for accountID %s", i, a.ID) + } + bytesConsumed += bytesRead + a.BlockIssuerKeys.Add(iotago.Ed25519PublicKeyHashBlockIssuerKeyFromImplicitAccountCreationAddress(&implicitAccountCreationAddress)) default: return bytesConsumed, ierrors.Wrapf(err, "unsupported block issuer key type %d for accountID %s at offset %d", blockIssuerKeyType, a.ID, i) } diff --git a/pkg/protocol/engine/accounts/mana/manager.go b/pkg/protocol/engine/accounts/mana/manager.go index efc12589b..7ea1a90e8 100644 --- a/pkg/protocol/engine/accounts/mana/manager.go +++ b/pkg/protocol/engine/accounts/mana/manager.go @@ -3,8 +3,10 @@ package mana import ( "github.com/zyedidia/generic/cache" + "github.com/iotaledger/hive.go/core/safemath" "github.com/iotaledger/hive.go/ds" "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/module" "github.com/iotaledger/hive.go/runtime/syncutils" "github.com/iotaledger/iota-core/pkg/protocol/engine/accounts" @@ -45,12 +47,15 @@ func (m *Manager) GetManaOnAccount(accountID iotago.AccountID, currentSlot iotag if err != nil { return 0, ierrors.Errorf("failed to resolve AccountOutput for %s in slot %s: %w", accountID, currentSlot, err) } - minDeposit := m.apiProvider.CurrentAPI().ProtocolParameters().RentStructure().MinDeposit(output.Output()) - if output.BaseTokenAmount() <= minDeposit { - mana = accounts.NewMana(output.StoredMana(), 0, output.SlotCreated()) - } else { - mana = accounts.NewMana(output.StoredMana(), output.BaseTokenAmount()-minDeposit, output.SlotCreated()) + minDeposit, err := m.apiProvider.CurrentAPI().RentStructure().MinDeposit(output.Output()) + if err != nil { + return 0, ierrors.Errorf("failed to get min deposit for %s: %w", accountID, err) + } + excessBaseTokens, err := safemath.SafeSub(output.BaseTokenAmount(), minDeposit) + if err != nil { + excessBaseTokens = 0 } + mana = accounts.NewMana(output.StoredMana(), excessBaseTokens, output.SlotCreated()) if !exists { m.manaVectorCache.Put(accountID, mana) @@ -92,12 +97,12 @@ func (m *Manager) ApplyDiff(slot iotago.SlotIndex, destroyedAccounts ds.Set[iota for accountID, output := range accountOutputs { mana, exists := m.manaVectorCache.Get(accountID) if exists { - minDeposit := m.apiProvider.CurrentAPI().ProtocolParameters().RentStructure().MinDeposit(output.Output()) - if output.BaseTokenAmount() <= minDeposit { - mana.Update(output.StoredMana(), 0, slot) - } else { - mana.Update(output.StoredMana(), output.BaseTokenAmount()-minDeposit, slot) + minDeposit := lo.PanicOnErr(m.apiProvider.CurrentAPI().RentStructure().MinDeposit(output.Output())) + excessBaseTokens, err := safemath.SafeSub(output.BaseTokenAmount(), minDeposit) + if err != nil { + excessBaseTokens = 0 } + mana.Update(output.StoredMana(), excessBaseTokens, slot) } } } diff --git a/pkg/protocol/engine/attestation/slotattestation/testframework_test.go b/pkg/protocol/engine/attestation/slotattestation/testframework_test.go index 76fb311dc..638458175 100644 --- a/pkg/protocol/engine/attestation/slotattestation/testframework_test.go +++ b/pkg/protocol/engine/attestation/slotattestation/testframework_test.go @@ -72,7 +72,7 @@ func NewTestFramework(test *testing.T) *TestFramework { iotago.NewV3ProtocolParameters( iotago.WithNetworkOptions("TestJungle", "tgl"), iotago.WithSupplyOptions(10000, 0, 0, 0, 0, 0, 0), - iotago.WithLivenessOptions(1, 1, 2, 8), + iotago.WithLivenessOptions(10, 10, 1, 2, 8), ), ) diff --git a/pkg/protocol/engine/blocks/block.go b/pkg/protocol/engine/blocks/block.go index 7fe161d58..a87d53467 100644 --- a/pkg/protocol/engine/blocks/block.go +++ b/pkg/protocol/engine/blocks/block.go @@ -162,12 +162,12 @@ func (b *Block) Payload() iotago.Payload { return b.modelBlock.Payload() } -func (b *Block) Transaction() (tx *iotago.Transaction, hasTransaction bool) { +func (b *Block) SignedTransaction() (tx *iotago.SignedTransaction, hasTransaction bool) { if b.modelBlock == nil { return nil, false } - return b.modelBlock.Transaction() + return b.modelBlock.SignedTransaction() } func (b *Block) BasicBlock() (basicBlock *iotago.BasicBlock, isBasicBlock bool) { @@ -383,6 +383,13 @@ func (b *Block) AddWitness(seat account.SeatIndex) (added bool) { return b.witnesses.Add(seat) } +func (b *Block) WitnessCount() int { + b.mutex.RLock() + defer b.mutex.RUnlock() + + return b.witnesses.Size() +} + func (b *Block) Witnesses() []account.SeatIndex { b.mutex.RLock() defer b.mutex.RUnlock() diff --git a/pkg/protocol/engine/booker/inmemorybooker/booker.go b/pkg/protocol/engine/booker/inmemorybooker/booker.go index 93fabc322..2a9e123f5 100644 --- a/pkg/protocol/engine/booker/inmemorybooker/booker.go +++ b/pkg/protocol/engine/booker/inmemorybooker/booker.go @@ -171,7 +171,7 @@ func (b *Booker) inheritConflicts(block *blocks.Block) (conflictIDs ds.Set[iotag case iotago.ShallowLikeParentType: // Check whether the parent contains a conflicting TX, // otherwise reference is invalid and the block should be marked as invalid as well. - if tx, hasTx := parentBlock.Transaction(); !hasTx || !parentBlock.PayloadConflictIDs().Has(lo.PanicOnErr(tx.ID())) { + if tx, hasTx := parentBlock.SignedTransaction(); !hasTx || !parentBlock.PayloadConflictIDs().Has(lo.PanicOnErr(tx.ID())) { return nil, ierrors.Wrapf(err, "shallow like parent %s does not contain a conflicting transaction", parent.ID.String()) } diff --git a/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter.go b/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter.go index 7c4c0a17a..952f3d2e3 100644 --- a/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter.go +++ b/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter.go @@ -121,10 +121,10 @@ func (c *CommitmentFilter) evaluateBlock(block *blocks.Block) { Reason: ierrors.Wrapf(err, "could not calculate Mana cost for block"), }) } - if basicBlock.BurnedMana < manaCost { + if basicBlock.MaxBurnedMana < manaCost { c.events.BlockFiltered.Trigger(&commitmentfilter.BlockFilteredEvent{ Block: block, - Reason: ierrors.Errorf("block issuer account %s burned insufficient Mana, required %d, burned %d", block.ProtocolBlock().IssuerID, manaCost, basicBlock.BurnedMana), + Reason: ierrors.Errorf("block issuer account %s burned insufficient Mana, required %d, burned %d", block.ProtocolBlock().IssuerID, manaCost, basicBlock.MaxBurnedMana), }) return @@ -154,12 +154,22 @@ func (c *CommitmentFilter) evaluateBlock(block *blocks.Block) { switch signature := block.ProtocolBlock().Signature.(type) { case *iotago.Ed25519Signature: if !accountData.BlockIssuerKeys.Has(iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(signature.PublicKey)) { - c.events.BlockFiltered.Trigger(&commitmentfilter.BlockFilteredEvent{ - Block: block, - Reason: ierrors.Wrapf(ErrInvalidSignature, "block issuer account %s does not have public key %s in slot %d", block.ProtocolBlock().IssuerID, signature.PublicKey, block.ProtocolBlock().SlotCommitmentID.Slot()), - }) - - return + // If the block issuer does not have the public key in the slot commitment, check if it is an implicit account with the corresponding address. + // There must be at least one block issuer key on any account, so extracting index 0 is fine. + // For implicit accounts there is exactly one key, so we do not have to check any other indices. + blockIssuerKey := accountData.BlockIssuerKeys[0] + // Implicit Accounts can only have Block Issuer Keys of type Ed25519PublicKeyHashBlockIssuerKey. + bikPubKeyHash, isBikPubKeyHash := blockIssuerKey.(*iotago.Ed25519PublicKeyHashBlockIssuerKey) + + // Filter the block if it's not a Block Issuer Key from an Implicit Account or if the Pub Key Hashes do not match. + if !isBikPubKeyHash || bikPubKeyHash.PublicKeyHash != iotago.Ed25519PublicKeyHashBlockIssuerKeyFromPublicKey(signature.PublicKey[:]).PublicKeyHash { + c.events.BlockFiltered.Trigger(&commitmentfilter.BlockFilteredEvent{ + Block: block, + Reason: ierrors.Wrapf(ErrInvalidSignature, "block issuer account %s does not have block issuer key corresponding to public key %s in slot %d", block.ProtocolBlock().IssuerID, signature.PublicKey, block.ProtocolBlock().SlotCommitmentID.Index()), + }) + + return + } } signingMessage, err := block.ProtocolBlock().SigningMessage() if err != nil { diff --git a/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter_test.go b/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter_test.go index 902e5d551..ab301e272 100644 --- a/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter_test.go +++ b/pkg/protocol/engine/commitmentfilter/accountsfilter/commitmentfilter_test.go @@ -116,7 +116,7 @@ func (t *TestFramework) IssueSignedBlockAtSlotWithBurnedMana(alias string, slot StrongParents(iotago.BlockIDs{}). IssuingTime(apiForSlot.TimeProvider().SlotStartTime(slot)). SlotCommitmentID(commitmentID). - BurnedMana(burnedMana). + MaxBurnedMana(burnedMana). Sign(iotago.AccountID(addr[:]), keyPair.PrivateKey[:]). Build() require.NoError(t.Test, err) @@ -137,6 +137,7 @@ func TestCommitmentFilter_NoAccount(t *testing.T) { tf.CommitmentFilter.events.BlockFiltered.Hook(func(event *commitmentfilter.BlockFilteredEvent) { require.NotEqual(t, "withAccount", event.Block.ID().Alias()) + require.NotEqual(t, "withImplicitAccount", event.Block.ID().Alias()) }) keyPair := ed25519.GenerateKeyPair() @@ -153,7 +154,7 @@ func TestCommitmentFilter_NoAccount(t *testing.T) { addr := iotago.Ed25519AddressFromPubKey(keyPair.PublicKey[:]) accountID := iotago.AccountID(addr[:]) - // register the account in the proxy account manager + // register the accounts in the proxy account manager tf.AddAccountData( accountID, accounts.NewAccountData( @@ -162,13 +163,26 @@ func TestCommitmentFilter_NoAccount(t *testing.T) { accounts.WithBlockIssuerKeys(iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(keyPair.PublicKey)), ), ) + keyPairImplicitAccount := ed25519.GenerateKeyPair() + implicitAddress := iotago.ImplicitAccountCreationAddressFromPubKey(keyPairImplicitAccount.PublicKey[:]) + implicitAccountID := iotago.AccountID(implicitAddress[:]) + tf.AddAccountData( + implicitAccountID, + accounts.NewAccountData( + implicitAccountID, + accounts.WithExpirySlot(iotago.MaxSlotIndex), + accounts.WithBlockIssuerKeys(iotago.Ed25519PublicKeyHashBlockIssuerKeyFromImplicitAccountCreationAddress(implicitAddress)), + ), + ) tf.AddRMCData(currentSlot-currentAPI.ProtocolParameters().MaxCommittableAge(), iotago.Mana(0)) tf.IssueSignedBlockAtSlot("withAccount", currentSlot, commitmentID, keyPair) - otherKeyPair := ed25519.GenerateKeyPair() - tf.IssueSignedBlockAtSlot("noAccount", currentSlot, commitmentID, otherKeyPair) + keyPairNoAccount := ed25519.GenerateKeyPair() + tf.IssueSignedBlockAtSlot("noAccount", currentSlot, commitmentID, keyPairNoAccount) + + tf.IssueSignedBlockAtSlot("withImplicitAccount", currentSlot, commitmentID, keyPairImplicitAccount) } func TestCommitmentFilter_BurnedMana(t *testing.T) { diff --git a/pkg/protocol/engine/ledger/ledger/ledger.go b/pkg/protocol/engine/ledger/ledger/ledger.go index 2292435a0..f9bf12815 100644 --- a/pkg/protocol/engine/ledger/ledger/ledger.go +++ b/pkg/protocol/engine/ledger/ledger/ledger.go @@ -123,7 +123,7 @@ func (l *Ledger) OnTransactionAttached(handler func(transaction mempool.Transact } func (l *Ledger) AttachTransaction(block *blocks.Block) (transactionMetadata mempool.TransactionMetadata, containsTransaction bool) { - if transaction, hasTransaction := block.Transaction(); hasTransaction { + if transaction, hasTransaction := block.SignedTransaction(); hasTransaction { transactionMetadata, err := l.memPool.AttachTransaction(transaction, block.ID()) if err != nil { l.retainTransactionFailure(block.ID(), err) @@ -212,7 +212,7 @@ func (l *Ledger) AddGenesisUnspentOutput(unspentOutput *utxoledger.Output) error func (l *Ledger) TrackBlock(block *blocks.Block) { l.accountsLedger.TrackBlock(block) - if _, hasTransaction := block.Transaction(); hasTransaction { + if _, hasTransaction := block.SignedTransaction(); hasTransaction { l.memPool.MarkAttachmentIncluded(block.ID()) } @@ -382,11 +382,19 @@ func (l *Ledger) prepareAccountDiffs(accountDiffs map[iotago.AccountID]*model.Ac // case 1. continue } - accountDiff.NewOutputID = createdOutput.OutputID() - accountDiff.PreviousOutputID = consumedOutput.OutputID() + // case 2. + // created output can never be an implicit account as these can not be transitioned, but consumed output can be. + switch consumedOutput.Output().Type() { + case iotago.OutputAccount: + accountDiff.PreviousExpirySlot = consumedOutput.Output().FeatureSet().BlockIssuer().ExpirySlot + case iotago.OutputBasic: + accountDiff.PreviousExpirySlot = iotago.MaxSlotIndex + } + + accountDiff.PreviousOutputID = consumedOutput.OutputID() + accountDiff.NewOutputID = createdOutput.OutputID() accountDiff.NewExpirySlot = createdOutput.Output().FeatureSet().BlockIssuer().ExpirySlot - accountDiff.PreviousExpirySlot = consumedOutput.Output().FeatureSet().BlockIssuer().ExpirySlot oldPubKeysSet := accountData.BlockIssuerKeys newPubKeysSet := iotago.NewBlockIssuerKeys() @@ -438,14 +446,24 @@ func (l *Ledger) prepareAccountDiffs(accountDiffs map[iotago.AccountID]*model.Ac // have some values from the allotment, so no need to set them explicitly. accountDiff.NewOutputID = createdOutput.OutputID() accountDiff.PreviousOutputID = iotago.EmptyOutputID - accountDiff.NewExpirySlot = createdOutput.Output().FeatureSet().BlockIssuer().ExpirySlot accountDiff.PreviousExpirySlot = 0 - accountDiff.BlockIssuerKeysAdded = createdOutput.Output().FeatureSet().BlockIssuer().BlockIssuerKeys - if stakingFeature := createdOutput.Output().FeatureSet().Staking(); stakingFeature != nil { - accountDiff.ValidatorStakeChange = int64(stakingFeature.StakedAmount) - accountDiff.StakeEndEpochChange = int64(stakingFeature.EndEpoch) - accountDiff.FixedCostChange = int64(stakingFeature.FixedCost) + switch createdOutput.Output().Type() { + // for account outputs, get block issuer keys from the block issuer feature, and check for staking info. + case iotago.OutputAccount: + accountDiff.BlockIssuerKeysAdded = createdOutput.Output().FeatureSet().BlockIssuer().BlockIssuerKeys + accountDiff.NewExpirySlot = createdOutput.Output().FeatureSet().BlockIssuer().ExpirySlot + if stakingFeature := createdOutput.Output().FeatureSet().Staking(); stakingFeature != nil { + accountDiff.ValidatorStakeChange = int64(stakingFeature.StakedAmount) + accountDiff.StakeEndEpochChange = int64(stakingFeature.EndEpoch) + accountDiff.FixedCostChange = int64(stakingFeature.FixedCost) + } + // for basic outputs (implicit accounts), get block issuer keys from the address in the unlock conditions. + case iotago.OutputBasic: + // If the Output is a Basic Output it can only be here if the address is an ImplicitAccountCreationAddress. + address, _ := createdOutput.Output().UnlockConditionSet().Address().Address.(*iotago.ImplicitAccountCreationAddress) + accountDiff.BlockIssuerKeysAdded = iotago.NewBlockIssuerKeys(iotago.Ed25519PublicKeyHashBlockIssuerKeyFromImplicitAccountCreationAddress(address)) + accountDiff.NewExpirySlot = iotago.MaxSlotIndex } } } @@ -486,6 +504,14 @@ func (l *Ledger) processCreatedAndConsumedAccountOutputs(stateDiff mempool.State // the delegation output was created => determine later if we need to add the stake to the validator delegation, _ := createdOutput.Output().(*iotago.DelegationOutput) createdAccountDelegation[delegation.DelegationID] = delegation + + case iotago.OutputBasic: + // if a basic output is sent to an implicit account creation address, we need to create the account + if createdOutput.Output().UnlockConditionSet().Address().Address.Type() == iotago.AddressImplicitAccountCreation { + accountID := iotago.AccountIDFromOutputID(outputID) + l.events.AccountCreated.Trigger(accountID) + createdAccounts[accountID] = createdOutput + } } return true @@ -506,7 +532,7 @@ func (l *Ledger) processCreatedAndConsumedAccountOutputs(stateDiff mempool.State switch spentOutput.OutputType() { case iotago.OutputAccount: consumedAccount, _ := spentOutput.Output().(*iotago.AccountOutput) - // if we transition / destroy an account that doesn't have a block issuer feature or staking, we don't need to track the changes. + // if we transition / destroy an account output that doesn't have a block issuer feature or staking, we don't need to track the changes. if consumedAccount.FeatureSet().BlockIssuer() == nil && consumedAccount.FeatureSet().Staking() == nil { return true } @@ -529,6 +555,13 @@ func (l *Ledger) processCreatedAndConsumedAccountOutputs(stateDiff mempool.State accountDiff := getAccountDiff(accountDiffs, delegationOutput.ValidatorAddress.AccountID()) accountDiff.DelegationStakeChange -= int64(delegationOutput.DelegatedAmount) } + + case iotago.OutputBasic: + // if a basic output (implicit account) is consumed, get the accountID as hash of the output ID. + if spentOutput.Output().UnlockConditionSet().Address().Address.Type() == iotago.AddressImplicitAccountCreation { + accountID := iotago.AccountIDFromOutputID(outputID) + consumedAccounts[accountID] = spentOutput + } } return true @@ -551,7 +584,7 @@ func (l *Ledger) processStateDiffTransactions(stateDiff mempool.StateDiff) (spen accountDiffs = make(map[iotago.AccountID]*model.AccountDiff) stateDiff.ExecutedTransactions().ForEach(func(txID iotago.TransactionID, txWithMeta mempool.TransactionMetadata) bool { - tx, ok := txWithMeta.Transaction().(*iotago.Transaction) + tx, ok := txWithMeta.Transaction().(*iotago.SignedTransaction) if !ok { err = iotago.ErrTxTypeInvalid return false @@ -586,7 +619,7 @@ func (l *Ledger) processStateDiffTransactions(stateDiff mempool.StateDiff) (spen // process allotments { - for _, allotment := range tx.Essence.Allotments { + for _, allotment := range tx.Transaction.Allotments { // in case it didn't exist, allotments won't change the outputID of the Account, // so the diff defaults to empty new and previous outputIDs accountDiff := getAccountDiff(accountDiffs, allotment.AccountID) diff --git a/pkg/protocol/engine/ledger/ledger/vm.go b/pkg/protocol/engine/ledger/ledger/vm.go index 53a054cdc..714c85c01 100644 --- a/pkg/protocol/engine/ledger/ledger/vm.go +++ b/pkg/protocol/engine/ledger/ledger/vm.go @@ -11,17 +11,14 @@ import ( ) func (l *Ledger) executeStardustVM(_ context.Context, stateTransition mempool.Transaction, inputStates []mempool.OutputState, timeReference mempool.ContextState) ([]mempool.OutputState, error) { - tx, ok := stateTransition.(*iotago.Transaction) + tx, ok := stateTransition.(*iotago.SignedTransaction) if !ok { return nil, iotago.ErrTxTypeInvalid } inputSet := iotagovm.InputSet{} - for _, inputState := range inputStates { - inputSet[inputState.OutputID()] = iotagovm.OutputWithCreationSlot{ - Output: inputState.Output(), - CreationSlot: inputState.SlotCreated(), - } + for _, input := range inputStates { + inputSet[input.OutputID()] = input.Output() } resolvedInputs := iotagovm.ResolvedInputs{ InputSet: inputSet, @@ -122,7 +119,7 @@ func (l *Ledger) executeStardustVM(_ context.Context, stateTransition mempool.Tr created = append(created, &ExecutionOutput{ outputID: outputID, output: output, - creationSlot: tx.Essence.CreationSlot, + creationSlot: tx.Transaction.CreationSlot, }) } diff --git a/pkg/protocol/engine/ledger/tests/output.go b/pkg/protocol/engine/ledger/tests/output.go index 3ba6c946b..19ecabac0 100644 --- a/pkg/protocol/engine/ledger/tests/output.go +++ b/pkg/protocol/engine/ledger/tests/output.go @@ -16,7 +16,7 @@ func (m *MockedOutput) WorkScore(_ *iotago.WorkScoreStructure) (iotago.WorkScore panic("implement me") } -func (m *MockedOutput) VBytes(_ *iotago.RentStructure, _ iotago.VBytesFunc) iotago.VBytes { +func (m *MockedOutput) StorageScore(_ *iotago.RentStructure, _ iotago.StorageScoreFunc) iotago.StorageScore { panic("implement me") } diff --git a/pkg/protocol/engine/tipmanager/tests/testframework.go b/pkg/protocol/engine/tipmanager/tests/testframework.go index 8eb436e16..8f6a74118 100644 --- a/pkg/protocol/engine/tipmanager/tests/testframework.go +++ b/pkg/protocol/engine/tipmanager/tests/testframework.go @@ -20,21 +20,26 @@ import ( type TestFramework struct { Instance *tipmanagerv1.TipManager - blockIDsByAlias map[string]iotago.BlockID - blocksByID map[iotago.BlockID]*blocks.Block - test *testing.T + blockIDsByAlias map[string]iotago.BlockID + tipMetadataByAlias map[string]tipmanager.TipMetadata + blocksByID map[iotago.BlockID]*blocks.Block + test *testing.T + + API iotago.API } func NewTestFramework(test *testing.T) *TestFramework { t := &TestFramework{ - blockIDsByAlias: make(map[string]iotago.BlockID), - blocksByID: make(map[iotago.BlockID]*blocks.Block), - test: test, + blockIDsByAlias: make(map[string]iotago.BlockID), + tipMetadataByAlias: make(map[string]tipmanager.TipMetadata), + blocksByID: make(map[iotago.BlockID]*blocks.Block), + test: test, + API: tpkg.TestAPI, } t.blockIDsByAlias["Genesis"] = iotago.EmptyBlockID() - t.Instance = tipmanagerv1.NewTipManager(func(blockID iotago.BlockID) (block *blocks.Block, exists bool) { + t.Instance = tipmanagerv1.New(func(blockID iotago.BlockID) (block *blocks.Block, exists bool) { block, exists = t.blocksByID[blockID] return block, exists }) @@ -43,11 +48,13 @@ func NewTestFramework(test *testing.T) *TestFramework { } func (t *TestFramework) AddBlock(alias string) tipmanager.TipMetadata { - return t.Instance.AddBlock(t.Block(alias)) + t.tipMetadataByAlias[alias] = t.Instance.AddBlock(t.Block(alias)) + + return t.tipMetadataByAlias[alias] } -func (t *TestFramework) CreateBlock(alias string, parents map[iotago.ParentsType][]string) *blocks.Block { - blockBuilder := builder.NewBasicBlockBuilder(tpkg.TestAPI) +func (t *TestFramework) CreateBlock(alias string, parents map[iotago.ParentsType][]string, optBlockBuilder ...func(*builder.BasicBlockBuilder)) *blocks.Block { + blockBuilder := builder.NewBasicBlockBuilder(t.API) blockBuilder.IssuingTime(time.Now()) if strongParents, strongParentsExist := parents[iotago.StrongParentType]; strongParentsExist { @@ -60,6 +67,10 @@ func (t *TestFramework) CreateBlock(alias string, parents map[iotago.ParentsType blockBuilder.ShallowLikeParents(lo.Map(shallowLikeParents, t.BlockID)) } + if len(optBlockBuilder) > 0 { + optBlockBuilder[0](blockBuilder) + } + block, err := blockBuilder.Build() require.NoError(t.test, err) @@ -82,6 +93,13 @@ func (t *TestFramework) Block(alias string) *blocks.Block { return block } +func (t *TestFramework) TipMetadata(alias string) tipmanager.TipMetadata { + tipMetadata, tipMetadataExists := t.tipMetadataByAlias[alias] + require.True(t.test, tipMetadataExists) + + return tipMetadata +} + func (t *TestFramework) BlockID(alias string) iotago.BlockID { blockID, blockIDExists := t.blockIDsByAlias[alias] require.True(t.test, blockIDExists, "blockID for alias '%s' does not exist", alias) @@ -89,10 +107,14 @@ func (t *TestFramework) BlockID(alias string) iotago.BlockID { return blockID } -func (t *TestFramework) AssertStrongTips(aliases ...string) { +func (t *TestFramework) RequireStrongTips(aliases ...string) { for _, alias := range aliases { require.True(t.test, ds.NewSet(lo.Map(t.Instance.StrongTips(), tipmanager.TipMetadata.ID)...).Has(t.BlockID(alias)), "strongTips does not contain block '%s'", alias) } require.Equal(t.test, len(aliases), len(t.Instance.StrongTips()), "strongTips size does not match") } + +func (t *TestFramework) RequireLivenessThresholdReached(alias string, expected bool) { + require.Equal(t.test, expected, t.TipMetadata(alias).LivenessThresholdReached().Get()) +} diff --git a/pkg/protocol/engine/tipmanager/tests/tipmanager_test.go b/pkg/protocol/engine/tipmanager/tests/tipmanager_test.go index 6492ff402..b994fa882 100644 --- a/pkg/protocol/engine/tipmanager/tests/tipmanager_test.go +++ b/pkg/protocol/engine/tipmanager/tests/tipmanager_test.go @@ -21,13 +21,13 @@ func TestTipManager(t *testing.T) { }) tf.AddBlock("Bernd").TipPool().Set(tipmanager.StrongTipPool) - tf.AssertStrongTips("Bernd") + tf.RequireStrongTips("Bernd") tf.AddBlock("Bernd1").TipPool().Set(tipmanager.StrongTipPool) - tf.AssertStrongTips("Bernd1") + tf.RequireStrongTips("Bernd1") tf.AddBlock("Bernd1.1").TipPool().Set(tipmanager.StrongTipPool) - tf.AssertStrongTips("Bernd1", "Bernd1.1") + tf.RequireStrongTips("Bernd1", "Bernd1.1") } func Test_Orphanage(t *testing.T) { @@ -44,15 +44,15 @@ func Test_Orphanage(t *testing.T) { }) tf.AddBlock("A").TipPool().Set(tipmanager.StrongTipPool) - tf.AssertStrongTips("A") + tf.RequireStrongTips("A") blockB := tf.AddBlock("B") blockB.TipPool().Set(tipmanager.StrongTipPool) - tf.AssertStrongTips("A", "B") + tf.RequireStrongTips("A", "B") tf.AddBlock("C").TipPool().Set(tipmanager.StrongTipPool) - tf.AssertStrongTips("C") + tf.RequireStrongTips("C") blockB.LivenessThresholdReached().Trigger() - tf.AssertStrongTips("A") + tf.RequireStrongTips("A") } diff --git a/pkg/protocol/engine/tipmanager/v1/provider.go b/pkg/protocol/engine/tipmanager/v1/provider.go index fe44998a1..abcc0d162 100644 --- a/pkg/protocol/engine/tipmanager/v1/provider.go +++ b/pkg/protocol/engine/tipmanager/v1/provider.go @@ -4,15 +4,14 @@ import ( "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/hive.go/runtime/module" - "github.com/iotaledger/hive.go/runtime/options" "github.com/iotaledger/iota-core/pkg/protocol/engine" "github.com/iotaledger/iota-core/pkg/protocol/engine/tipmanager" ) // NewProvider creates a new TipManager provider, that can be used to inject the component into an engine. -func NewProvider(opts ...options.Option[TipManager]) module.Provider[*engine.Engine, tipmanager.TipManager] { +func NewProvider() module.Provider[*engine.Engine, tipmanager.TipManager] { return module.Provide(func(e *engine.Engine) tipmanager.TipManager { - t := NewTipManager(e.BlockCache.Block, opts...) + t := New(e.BlockCache.Block) e.HookConstructed(func() { tipWorker := e.Workers.CreatePool("AddTip", 2) diff --git a/pkg/protocol/engine/tipmanager/v1/tipmanager.go b/pkg/protocol/engine/tipmanager/v1/tipmanager.go index bb68aa8a5..671e45327 100644 --- a/pkg/protocol/engine/tipmanager/v1/tipmanager.go +++ b/pkg/protocol/engine/tipmanager/v1/tipmanager.go @@ -6,7 +6,6 @@ import ( "github.com/iotaledger/hive.go/lo" "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/iota-core/pkg/protocol/engine/blocks" "github.com/iotaledger/iota-core/pkg/protocol/engine/tipmanager" @@ -40,15 +39,20 @@ type TipManager struct { module.Module } -// NewTipManager creates a new TipManager. -func NewTipManager(blockRetriever func(blockID iotago.BlockID) (block *blocks.Block, exists bool), opts ...options.Option[TipManager]) *TipManager { - return options.Apply(&TipManager{ +// New creates a new TipManager. +func New(blockRetriever func(blockID iotago.BlockID) (block *blocks.Block, exists bool)) *TipManager { + t := &TipManager{ retrieveBlock: blockRetriever, tipMetadataStorage: shrinkingmap.New[iotago.SlotIndex, *shrinkingmap.ShrinkingMap[iotago.BlockID, *TipMetadata]](), strongTipSet: randommap.New[iotago.BlockID, *TipMetadata](), weakTipSet: randommap.New[iotago.BlockID, *TipMetadata](), blockAdded: event.New1[tipmanager.TipMetadata](), - }, opts, (*TipManager).TriggerConstructed) + } + + t.TriggerConstructed() + t.TriggerInitialized() + + return t } // AddBlock adds a Block to the TipManager and returns the TipMetadata if the Block was added successfully. @@ -99,8 +103,11 @@ func (t *TipManager) Evict(slot iotago.SlotIndex) { } } -// Shutdown does nothing but is required by the module.Interface. -func (t *TipManager) Shutdown() {} +// Shutdown marks the TipManager as shutdown. +func (t *TipManager) Shutdown() { + t.TriggerShutdown() + t.TriggerStopped() +} // setupBlockMetadata sets up the behavior of the given Block. func (t *TipManager) setupBlockMetadata(tipMetadata *TipMetadata) { @@ -139,7 +146,13 @@ func (t *TipManager) forEachParentByType(block *blocks.Block, consumer func(pare for _, parent := range block.ParentsWithType() { if metadataStorage := t.metadataStorage(parent.ID.Slot()); metadataStorage != nil { - if parentMetadata, created := metadataStorage.GetOrCreate(parent.ID, func() *TipMetadata { return NewBlockMetadata(lo.Return1(t.retrieveBlock(parent.ID))) }); parentMetadata.Block() != nil { + // Make sure we don't add rootblocks back to the tips. + parentBlock, exists := t.retrieveBlock(parent.ID) + if !exists || parentBlock.IsRootBlock() { + continue + } + + if parentMetadata, created := metadataStorage.GetOrCreate(parent.ID, func() *TipMetadata { return NewBlockMetadata(parentBlock) }); parentMetadata.Block() != nil { consumer(parent.Type, parentMetadata) if created { diff --git a/pkg/protocol/engine/tipselection/tipselection.go b/pkg/protocol/engine/tipselection/tipselection.go index 83d758365..44bbae798 100644 --- a/pkg/protocol/engine/tipselection/tipselection.go +++ b/pkg/protocol/engine/tipselection/tipselection.go @@ -12,8 +12,8 @@ type TipSelection interface { // SelectTips selects the tips that should be used as references for a new block. SelectTips(count int) (references model.ParentReferences) - // SetLivenessThreshold sets the liveness threshold used for tip selection (it can only increase monotonically). - SetLivenessThreshold(threshold time.Time) + // SetAcceptanceTime updates the acceptance time of the TipSelection. + SetAcceptanceTime(acceptanceTime time.Time) (previousTime time.Time) // Interface embeds the required methods of the module.Interface. module.Interface diff --git a/pkg/protocol/engine/tipselection/v1/provider.go b/pkg/protocol/engine/tipselection/v1/provider.go index 067cdd0b8..ad9bb1d1b 100644 --- a/pkg/protocol/engine/tipselection/v1/provider.go +++ b/pkg/protocol/engine/tipselection/v1/provider.go @@ -1,38 +1,54 @@ package tipselectionv1 import ( + "math" + "time" + "github.com/iotaledger/hive.go/runtime/module" "github.com/iotaledger/hive.go/runtime/options" "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/tipmanager" "github.com/iotaledger/iota-core/pkg/protocol/engine/tipselection" ) // NewProvider creates a new TipSelection provider, that can be used to inject the component into an engine. func NewProvider(opts ...options.Option[TipSelection]) module.Provider[*engine.Engine, tipselection.TipSelection] { return module.Provide(func(e *engine.Engine) tipselection.TipSelection { - t := New(e, e.TipManager, e.Ledger.ConflictDAG(), e.Ledger.MemPool(), e.EvictionState.LatestRootBlocks, opts...) + t := New(opts...) e.HookConstructed(func() { - e.Ledger.HookInitialized(func() { + // wait for submodules to be constructed (so all of their properties are available) + module.OnAllConstructed(func() { + t.Construct(e.TipManager, e.Ledger.ConflictDAG(), e.Ledger.MemPool().TransactionMetadata, e.EvictionState.LatestRootBlocks, DynamicLivenessThreshold(e.SybilProtection.SeatManager().OnlineCommittee().Size)) + e.Events.AcceptedBlockProcessed.Hook(func(block *blocks.Block) { - t.SetLivenessThreshold(block.IssuingTime().Add(-e.CurrentAPI().LivenessThresholdDuration())) + t.SetAcceptanceTime(block.IssuingTime()) }) - - t.conflictDAG = e.Ledger.ConflictDAG() - t.memPool = e.Ledger.MemPool() - - t.TriggerInitialized() - }) - - e.TipManager.OnBlockAdded(t.classifyTip) + }, e.TipManager, e.Ledger, e.SybilProtection) }) - e.HookShutdown(func() { - t.TriggerShutdown() - t.TriggerStopped() - }) + e.HookShutdown(t.Shutdown) return t }) } + +// DynamicLivenessThreshold returns a function that calculates the liveness threshold for a tip. +func DynamicLivenessThreshold(committeeSizeProvider func() int) func(tip tipmanager.TipMetadata) time.Duration { + return func(tip tipmanager.TipMetadata) time.Duration { + // We want to scale the liveness threshold based on the number of witnesses: + // 0 witnesses: approval modifier is 0 -> LivenessThresholdLowerBound + // <=1/3: scale linearly + // >1/3: approval modifier is 1 -> LivenessThresholdUpperBound + var ( + params = tip.Block().ModelBlock().ProtocolBlock().API.ProtocolParameters() + livenessThresholdLowerBound = params.LivenessThresholdLowerBound() + livenessWindow = float64(params.LivenessThresholdUpperBound() - livenessThresholdLowerBound) + expectedWitnessCount = math.Ceil(float64(committeeSizeProvider()) / 3.0) + approvalModifier = math.Min(float64(tip.Block().WitnessCount())/expectedWitnessCount, 1.0) + ) + + return livenessThresholdLowerBound + time.Duration(approvalModifier*livenessWindow) + } +} diff --git a/pkg/protocol/engine/tipselection/v1/test_framework_test.go b/pkg/protocol/engine/tipselection/v1/test_framework_test.go new file mode 100644 index 000000000..8eeb61f02 --- /dev/null +++ b/pkg/protocol/engine/tipselection/v1/test_framework_test.go @@ -0,0 +1,92 @@ +package tipselectionv1_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/iotaledger/hive.go/runtime/options" + "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" + "github.com/iotaledger/iota-core/pkg/protocol/engine/ledger" + "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool" + "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool/conflictdag/conflictdagv1" + "github.com/iotaledger/iota-core/pkg/protocol/engine/tipmanager" + tipmanagertests "github.com/iotaledger/iota-core/pkg/protocol/engine/tipmanager/tests" + tipselectionv1 "github.com/iotaledger/iota-core/pkg/protocol/engine/tipselection/v1" + iotago "github.com/iotaledger/iota.go/v4" +) + +type TestFramework struct { + Instance *tipselectionv1.TipSelection + TipManager *tipmanagertests.TestFramework + + test *testing.T + createdBlocks map[iotago.BlockID]*blocks.Block + + expectedLivenessDuration func(tip tipmanager.TipMetadata) time.Duration + + optCommitteeSize int +} + +func NewTestFramework(test *testing.T, opts ...options.Option[TestFramework]) *TestFramework { + return options.Apply(&TestFramework{ + test: test, + createdBlocks: make(map[iotago.BlockID]*blocks.Block), + optCommitteeSize: 10, + }, opts, func(t *TestFramework) { + t.expectedLivenessDuration = tipselectionv1.DynamicLivenessThreshold(func() int { return t.optCommitteeSize }) + + transactionMetadataRetriever := func(iotago.TransactionID) (mempool.TransactionMetadata, bool) { + return nil, false + } + + rootBlocksRetriever := func() iotago.BlockIDs { + return iotago.BlockIDs{iotago.EmptyBlockID()} + } + + t.TipManager = tipmanagertests.NewTestFramework(test) + + t.Instance = tipselectionv1.New().Construct( + t.TipManager.Instance, + conflictdagv1.New[iotago.TransactionID, iotago.OutputID, ledger.BlockVoteRank](t.CommitteeSize), + transactionMetadataRetriever, + rootBlocksRetriever, + t.expectedLivenessDuration, + ) + }) +} + +func (t *TestFramework) LowerLivenessThreshold(alias string) time.Time { + block := t.TipManager.Block(alias) + + return block.IssuingTime().Add(block.ProtocolBlock().API.ProtocolParameters().LivenessThresholdLowerBound()) +} + +func (t *TestFramework) UpperLivenessThreshold(alias string) time.Time { + block := t.TipManager.Block(alias) + + return block.IssuingTime().Add(block.ProtocolBlock().API.ProtocolParameters().LivenessThresholdUpperBound()) +} + +func (t *TestFramework) ExpectedLivenessThreshold(alias string) time.Time { + tipMetadata := t.TipManager.TipMetadata(alias) + + return tipMetadata.Block().IssuingTime().Add(t.expectedLivenessDuration(tipMetadata)) +} + +func (t *TestFramework) RequireLivenessThreshold(alias string, expectedDuration time.Duration) { + tipMetadata := t.TipManager.TipMetadata(alias) + + require.Equal(t.test, expectedDuration, t.expectedLivenessDuration(tipMetadata)) +} + +func (t *TestFramework) CommitteeSize() int { + return t.optCommitteeSize +} + +func WithCommitteeSize(size int) options.Option[TestFramework] { + return func(args *TestFramework) { + args.optCommitteeSize = size + } +} diff --git a/pkg/protocol/engine/tipselection/v1/tipselection.go b/pkg/protocol/engine/tipselection/v1/tip_selection.go similarity index 71% rename from pkg/protocol/engine/tipselection/v1/tipselection.go rename to pkg/protocol/engine/tipselection/v1/tip_selection.go index 1d0ea5f95..c1c2977f6 100644 --- a/pkg/protocol/engine/tipselection/v1/tipselection.go +++ b/pkg/protocol/engine/tipselection/v1/tip_selection.go @@ -11,7 +11,6 @@ import ( "github.com/iotaledger/hive.go/runtime/options" "github.com/iotaledger/hive.go/runtime/timed" "github.com/iotaledger/iota-core/pkg/model" - "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/ledger" "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool" @@ -22,23 +21,26 @@ import ( // TipSelection is a component that is used to abstract away the tip selection strategy, used to issue new blocks. type TipSelection struct { - // rootBlocks is a function that returns the current root blocks. - rootBlocks func() iotago.BlockIDs - // tipManager is the TipManager that is used to access the tip related metadata. tipManager tipmanager.TipManager // conflictDAG is the ConflictDAG that is used to track conflicts. conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, iotago.OutputID, ledger.BlockVoteRank] - // memPool holds information about pending transactions. - memPool mempool.MemPool[ledger.BlockVoteRank] + // rootBlocks is a function that returns the current root blocks. + rootBlocks func() iotago.BlockIDs + + // livenessThreshold is a function that is used to determine the liveness threshold for a tip. + livenessThreshold func(tip tipmanager.TipMetadata) time.Duration + + // transactionMetadata holds a function that is used to retrieve the metadata of a transaction. + transactionMetadata func(iotago.TransactionID) (mempool.TransactionMetadata, bool) // livenessThresholdQueue holds a queue of tips that are waiting to reach the liveness threshold. livenessThresholdQueue timed.PriorityQueue[tipmanager.TipMetadata] - // livenessThreshold holds the current liveness threshold. - livenessThreshold reactive.Variable[time.Time] + // acceptanceTime holds the current acceptance time. + acceptanceTime reactive.Variable[time.Time] // optMaxStrongParents contains the maximum number of strong parents that are allowed. optMaxStrongParents int @@ -55,33 +57,43 @@ type TipSelection struct { // Module embeds the required methods of the module.Interface. module.Module - engine *engine.Engine } // New is the constructor for the TipSelection. -func New(e *engine.Engine, tipManager tipmanager.TipManager, conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, iotago.OutputID, ledger.BlockVoteRank], memPool mempool.MemPool[ledger.BlockVoteRank], rootBlocksRetriever func() iotago.BlockIDs, opts ...options.Option[TipSelection]) *TipSelection { +func New(opts ...options.Option[TipSelection]) *TipSelection { return options.Apply(&TipSelection{ - tipManager: tipManager, - engine: e, - conflictDAG: conflictDAG, - memPool: memPool, - rootBlocks: rootBlocksRetriever, - livenessThresholdQueue: timed.NewPriorityQueue[tipmanager.TipMetadata](true), - livenessThreshold: reactive.NewVariable[time.Time](), - optMaxStrongParents: 8, - optMaxLikedInsteadReferences: 8, - optMaxWeakReferences: 8, - }, opts, func(t *TipSelection) { - t.optMaxLikedInsteadReferencesPerParent = t.optMaxLikedInsteadReferences / 2 - - t.livenessThreshold.OnUpdate(func(_, threshold time.Time) { - for _, tip := range t.livenessThresholdQueue.PopUntil(threshold) { - tip.LivenessThresholdReached().Trigger() - } - }) + livenessThresholdQueue: timed.NewPriorityQueue[tipmanager.TipMetadata](true), + acceptanceTime: reactive.NewVariable[time.Time](monotonicallyIncreasing), + optMaxStrongParents: 8, + optMaxLikedInsteadReferences: 8, + optMaxLikedInsteadReferencesPerParent: 4, + optMaxWeakReferences: 8, + }, opts) +} - t.TriggerConstructed() +// Construct fills in the dependencies of the TipSelection and triggers the constructed and initialized events of the +// module. +// +// This method is separated from the constructor so the TipSelection can be initialized lazily after all dependencies +// are available. +func (t *TipSelection) Construct(tipManager tipmanager.TipManager, conflictDAG conflictdag.ConflictDAG[iotago.TransactionID, iotago.OutputID, ledger.BlockVoteRank], transactionMetadataRetriever func(iotago.TransactionID) (mempool.TransactionMetadata, bool), rootBlocksRetriever func() iotago.BlockIDs, livenessThresholdFunc func(tipmanager.TipMetadata) time.Duration) *TipSelection { + t.tipManager = tipManager + t.conflictDAG = conflictDAG + t.transactionMetadata = transactionMetadataRetriever + t.rootBlocks = rootBlocksRetriever + t.livenessThreshold = livenessThresholdFunc + + t.TriggerConstructed() + + t.acceptanceTime.OnUpdate(func(_, acceptanceTime time.Time) { + t.triggerLivenessThreshold(acceptanceTime) }) + + tipManager.OnBlockAdded(t.classifyTip) + + t.TriggerInitialized() + + return t } // SelectTips selects the tips that should be used as references for a new block. @@ -125,15 +137,16 @@ func (t *TipSelection) SelectTips(amount int) (references model.ParentReferences return references } -// SetLivenessThreshold sets the liveness threshold used for tip selection (it can only increase monotonically). -func (t *TipSelection) SetLivenessThreshold(threshold time.Time) { - t.livenessThreshold.Compute(func(currentThreshold time.Time) time.Time { - return lo.Cond(threshold.Before(currentThreshold), currentThreshold, threshold) - }) +// SetAcceptanceTime updates the acceptance time of the TipSelection. +func (t *TipSelection) SetAcceptanceTime(acceptanceTime time.Time) (previousValue time.Time) { + return t.acceptanceTime.Set(acceptanceTime) } -// Shutdown does nothing but is required by the module.Interface. -func (t *TipSelection) Shutdown() {} +// Shutdown triggers the shutdown of the TipSelection. +func (t *TipSelection) Shutdown() { + t.TriggerShutdown() + t.TriggerStopped() +} // classifyTip determines the initial tip pool of the given tip. func (t *TipSelection) classifyTip(tipMetadata tipmanager.TipMetadata) { @@ -145,14 +158,14 @@ func (t *TipSelection) classifyTip(tipMetadata tipmanager.TipMetadata) { tipMetadata.TipPool().Set(tipmanager.DroppedTipPool) } - t.livenessThresholdQueue.Push(tipMetadata, tipMetadata.Block().IssuingTime()) + t.livenessThresholdQueue.Push(tipMetadata, tipMetadata.Block().IssuingTime().Add(t.livenessThreshold(tipMetadata))) } // likedInsteadReferences returns the liked instead references that are required to be able to reference the given tip. func (t *TipSelection) likedInsteadReferences(likedConflicts ds.Set[iotago.TransactionID], tipMetadata tipmanager.TipMetadata) (references []iotago.BlockID, updatedLikedConflicts ds.Set[iotago.TransactionID], err error) { necessaryReferences := make(map[iotago.TransactionID]iotago.BlockID) if err = t.conflictDAG.LikedInstead(tipMetadata.Block().ConflictIDs()).ForEach(func(likedConflictID iotago.TransactionID) error { - transactionMetadata, exists := t.memPool.TransactionMetadata(likedConflictID) + transactionMetadata, exists := t.transactionMetadata(likedConflictID) if !exists { return ierrors.Errorf("transaction required for liked instead reference (%s) not found in mem-pool", likedConflictID) } @@ -215,6 +228,17 @@ func (t *TipSelection) isValidWeakTip(block *blocks.Block) bool { return t.conflictDAG.LikedInstead(block.PayloadConflictIDs()).Size() == 0 } +// triggerLivenessThreshold triggers the liveness threshold for all tips that have reached the given threshold. +func (t *TipSelection) triggerLivenessThreshold(threshold time.Time) { + for _, tip := range t.livenessThresholdQueue.PopUntil(threshold) { + if dynamicLivenessThreshold := tip.Block().IssuingTime().Add(t.livenessThreshold(tip)); dynamicLivenessThreshold.After(threshold) { + t.livenessThresholdQueue.Push(tip, dynamicLivenessThreshold) + } else { + tip.LivenessThresholdReached().Trigger() + } + } +} + // WithMaxStrongParents is an option for the TipSelection that allows to configure the maximum number of strong parents. func WithMaxStrongParents(maxStrongParents int) options.Option[TipSelection] { return func(tipManager *TipSelection) { @@ -236,3 +260,13 @@ func WithMaxWeakReferences(maxWeakReferences int) options.Option[TipSelection] { tipManager.optMaxWeakReferences = maxWeakReferences } } + +// monotonicallyIncreasing returns the maximum of the two given times which is used as a transformation function to make +// the acceptance time of the TipSelection monotonically increasing. +func monotonicallyIncreasing(currentTime time.Time, newTime time.Time) time.Time { + if currentTime.After(newTime) { + return currentTime + } + + return newTime +} diff --git a/pkg/protocol/engine/tipselection/v1/tip_selection_test.go b/pkg/protocol/engine/tipselection/v1/tip_selection_test.go new file mode 100644 index 000000000..a69695d55 --- /dev/null +++ b/pkg/protocol/engine/tipselection/v1/tip_selection_test.go @@ -0,0 +1,213 @@ +package tipselectionv1_test + +import ( + "math" + "testing" + "time" + + "github.com/stretchr/testify/require" + + iotago "github.com/iotaledger/iota.go/v4" +) + +func TestTipSelection_DynamicLivenessThreshold_NoWitnesses(t *testing.T) { + tf := NewTestFramework(t) + tf.TipManager.CreateBlock("Block", map[iotago.ParentsType][]string{iotago.StrongParentType: {"Genesis"}}) + tf.TipManager.AddBlock("Block") + + expectedLivenessThreshold := tf.ExpectedLivenessThreshold("Block") + require.Equal(t, tf.LowerLivenessThreshold("Block"), expectedLivenessThreshold) + + // assert initial state + { + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to just before liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThreshold.Add(-1)) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to reach liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThreshold) + + tf.TipManager.RequireLivenessThresholdReached("Block", true) + tf.TipManager.RequireStrongTips() + } +} + +func TestTipSelection_DynamicLivenessThreshold_WithSingleWitness(t *testing.T) { + tf := NewTestFramework(t) + tf.TipManager.CreateBlock("Block", map[iotago.ParentsType][]string{iotago.StrongParentType: {"Genesis"}}) + tf.TipManager.AddBlock("Block") + + expectedLivenessThresholdWithoutWitnesses := tf.ExpectedLivenessThreshold("Block") + require.Equal(t, tf.LowerLivenessThreshold("Block"), expectedLivenessThresholdWithoutWitnesses) + + // assert initial state + { + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to just before liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThresholdWithoutWitnesses.Add(-1)) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // add witness + tf.TipManager.Block("Block").AddWitness(0) + expectedLivenessThresholdWithOneWitness := tf.ExpectedLivenessThreshold("Block") + require.Less(t, expectedLivenessThresholdWithoutWitnesses.Unix(), expectedLivenessThresholdWithOneWitness.Unix()) + + // advance time to reach previous liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThresholdWithoutWitnesses) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to just before new liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThresholdWithOneWitness.Add(-1)) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to reach new liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThresholdWithOneWitness) + + tf.TipManager.RequireLivenessThresholdReached("Block", true) + tf.TipManager.RequireStrongTips() + } +} + +func TestTipSelection_DynamicLivenessThreshold_WithMaxWitnesses(t *testing.T) { + tf := NewTestFramework(t) + tf.TipManager.CreateBlock("Block", map[iotago.ParentsType][]string{iotago.StrongParentType: {"Genesis"}}) + tf.TipManager.AddBlock("Block") + + livenessThresholdZero := tf.ExpectedLivenessThreshold("Block") + require.Equal(t, tf.LowerLivenessThreshold("Block"), livenessThresholdZero) + + // assert initial state + { + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to just before liveness threshold + { + tf.Instance.SetAcceptanceTime(livenessThresholdZero.Add(-1)) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // add witnesses (not enough to reach max) + tf.TipManager.Block("Block").AddWitness(0) + tf.TipManager.Block("Block").AddWitness(1) + tf.TipManager.Block("Block").AddWitness(2) + livenessThresholdThree := tf.ExpectedLivenessThreshold("Block") + require.Less(t, livenessThresholdZero.Unix(), livenessThresholdThree.Unix()) + + // advance time to reach previous liveness threshold + { + tf.Instance.SetAcceptanceTime(livenessThresholdZero) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to just before new liveness threshold + { + tf.Instance.SetAcceptanceTime(livenessThresholdThree.Add(-1)) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // add witness (reaches max) + tf.TipManager.Block("Block").AddWitness(3) + livenessThresholdFour := tf.ExpectedLivenessThreshold("Block") + require.Less(t, livenessThresholdThree.Unix(), livenessThresholdFour.Unix()) + require.Equal(t, tf.UpperLivenessThreshold("Block"), livenessThresholdFour) + + // advance time to reach previous liveness threshold + { + tf.Instance.SetAcceptanceTime(livenessThresholdThree) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // advance time to just before new liveness threshold + { + tf.Instance.SetAcceptanceTime(livenessThresholdFour.Add(-1)) + + tf.TipManager.RequireLivenessThresholdReached("Block", false) + tf.TipManager.RequireStrongTips("Block") + } + + // add witness (reaches above max) + tf.TipManager.Block("Block").AddWitness(4) + expectedLivenessThresholdWithFiveWitness := tf.ExpectedLivenessThreshold("Block") + require.Equal(t, livenessThresholdFour, expectedLivenessThresholdWithFiveWitness) + require.Equal(t, tf.UpperLivenessThreshold("Block"), livenessThresholdFour) + + // advance time to reach new liveness threshold + { + tf.Instance.SetAcceptanceTime(expectedLivenessThresholdWithFiveWitness) + + tf.TipManager.RequireLivenessThresholdReached("Block", true) + tf.TipManager.RequireStrongTips() + } +} + +func TestDynamicLivenessThreshold(t *testing.T) { + const committeeSize = 10 + tf := NewTestFramework(t, WithCommitteeSize(committeeSize)) + tf.TipManager.CreateBlock("Block", map[iotago.ParentsType][]string{iotago.StrongParentType: {"Genesis"}}) + tf.TipManager.AddBlock("Block") + + livenessThresholdLowerBound := tf.TipManager.API.ProtocolParameters().LivenessThresholdLowerBound() + livenessWindow := float64(tf.TipManager.API.ProtocolParameters().LivenessThresholdUpperBound() - livenessThresholdLowerBound) + + tf.RequireLivenessThreshold("Block", livenessThresholdLowerBound) + + tf.TipManager.Block("Block").AddWitness(0) + tf.RequireLivenessThreshold("Block", livenessThresholdLowerBound+time.Duration(approvalModifier(1, committeeSize)*livenessWindow)) + + tf.TipManager.Block("Block").AddWitness(1) + tf.RequireLivenessThreshold("Block", livenessThresholdLowerBound+time.Duration(approvalModifier(2, committeeSize)*livenessWindow)) + + tf.TipManager.Block("Block").AddWitness(2) + tf.RequireLivenessThreshold("Block", livenessThresholdLowerBound+time.Duration(approvalModifier(3, committeeSize)*livenessWindow)) + + // We've reached > 1/3 -> liveness threshold should be at upper bound + tf.TipManager.Block("Block").AddWitness(3) + tf.RequireLivenessThreshold("Block", tf.TipManager.API.ProtocolParameters().LivenessThresholdUpperBound()) + + tf.TipManager.Block("Block").AddWitness(4) + tf.TipManager.Block("Block").AddWitness(5) + tf.TipManager.Block("Block").AddWitness(6) + tf.TipManager.Block("Block").AddWitness(7) + tf.TipManager.Block("Block").AddWitness(8) + tf.TipManager.Block("Block").AddWitness(9) + tf.RequireLivenessThreshold("Block", tf.TipManager.API.ProtocolParameters().LivenessThresholdUpperBound()) +} + +func approvalModifier(witnessCount float64, committeeSize float64) float64 { + return witnessCount / math.Ceil(committeeSize/3.0) +} diff --git a/pkg/protocol/engine/utxoledger/database_prefixes.go b/pkg/protocol/engine/utxoledger/database_prefixes.go index 0f347dd2b..12dcd559e 100644 --- a/pkg/protocol/engine/utxoledger/database_prefixes.go +++ b/pkg/protocol/engine/utxoledger/database_prefixes.go @@ -46,7 +46,7 @@ const ( 1 byte + 34 bytes Value: - TargetTransactionID (iotago.TransactionID) + TransactionAcceptedSlotIndex (iotago.SlotIndex) + TransactionCreationSlot (time.Time) + TargetTransactionID (iotago.SignedTransactionID) + TransactionAcceptedSlotIndex (iotago.SlotIndex) + TransactionCreationSlot (time.Time) 32 bytes + 8 bytes + 8 bytes Unspent Output: diff --git a/pkg/protocol/engine/utxoledger/output.go b/pkg/protocol/engine/utxoledger/output.go index 6f93a26fe..86b557651 100644 --- a/pkg/protocol/engine/utxoledger/output.go +++ b/pkg/protocol/engine/utxoledger/output.go @@ -64,7 +64,7 @@ func (o *Output) SlotBooked() iotago.SlotIndex { } func (o *Output) SlotCreated() iotago.SlotIndex { - return o.outputID.CreationSlotIndex() + return o.outputID.CreationSlot() } func (o *Output) OutputType() iotago.OutputType { @@ -142,10 +142,10 @@ func NewOutput(apiProvider iotago.APIProvider, blockID iotago.BlockID, slotBooke } var output iotago.Output - if len(transaction.Essence.Outputs) <= int(index) { + if len(transaction.Outputs) <= int(index) { return nil, ierrors.New("output not found") } - output = transaction.Essence.Outputs[int(index)] + output = transaction.Outputs[int(index)] outputID := iotago.OutputIDFromTransactionIDAndIndex(txID, index) return CreateOutput(apiProvider, outputID, blockID, slotBooked, output), nil diff --git a/pkg/protocol/engine/utxoledger/tpkg/equal.go b/pkg/protocol/engine/utxoledger/tpkg/equal.go index 13491215e..f32290577 100644 --- a/pkg/protocol/engine/utxoledger/tpkg/equal.go +++ b/pkg/protocol/engine/utxoledger/tpkg/equal.go @@ -24,7 +24,7 @@ func EqualOutput(t *testing.T, expected *utxoledger.Output, actual *utxoledger.O case iotago.TransIndepIdentOutput: expectedIdent = output.Ident() case iotago.TransDepIdentOutput: - expectedIdent = output.Chain().ToAddress() + expectedIdent = output.ChainID().ToAddress() default: require.Fail(t, "unsupported output type") } @@ -34,7 +34,7 @@ func EqualOutput(t *testing.T, expected *utxoledger.Output, actual *utxoledger.O case iotago.TransIndepIdentOutput: actualIdent = output.Ident() case iotago.TransDepIdentOutput: - actualIdent = output.Chain().ToAddress() + actualIdent = output.ChainID().ToAddress() default: require.Fail(t, "unsupported output type") } diff --git a/pkg/protocol/snapshotcreator/snapshotcreator.go b/pkg/protocol/snapshotcreator/snapshotcreator.go index 9bab2a3ce..a23983d2a 100644 --- a/pkg/protocol/snapshotcreator/snapshotcreator.go +++ b/pkg/protocol/snapshotcreator/snapshotcreator.go @@ -135,7 +135,7 @@ func createGenesisOutput(genesisTokenAmount iotago.BaseToken, genesisSeed []byte genesisWallet := mock.NewHDWallet("genesis", genesisSeed, 0) output := createOutput(genesisWallet.Address(), genesisTokenAmount) - if _, err := engineInstance.CurrentAPI().ProtocolParameters().RentStructure().CoversMinDeposit(output, genesisTokenAmount); err != nil { + if _, err := engineInstance.CurrentAPI().RentStructure().CoversMinDeposit(output, genesisTokenAmount); err != nil { return ierrors.Wrap(err, "min rent not covered by Genesis output with index 0") } @@ -153,7 +153,7 @@ func createGenesisAccounts(accounts []AccountDetails, engineInstance *engine.Eng for idx, genesisAccount := range accounts { output := createAccount(genesisAccount.AccountID, genesisAccount.Address, genesisAccount.Amount, genesisAccount.Mana, genesisAccount.IssuerKey, genesisAccount.ExpirySlot, genesisAccount.StakedAmount, genesisAccount.StakingEpochEnd, genesisAccount.FixedCost) - if _, err := engineInstance.CurrentAPI().ProtocolParameters().RentStructure().CoversMinDeposit(output, genesisAccount.Amount); err != nil { + if _, err := engineInstance.CurrentAPI().RentStructure().CoversMinDeposit(output, genesisAccount.Amount); err != nil { return ierrors.Wrapf(err, "min rent not covered by account output with index %d", idx+1) } diff --git a/pkg/storage/testframework_test.go b/pkg/storage/testframework_test.go index 127375e42..e6eea9d8f 100644 --- a/pkg/storage/testframework_test.go +++ b/pkg/storage/testframework_test.go @@ -93,7 +93,7 @@ func (t *TestFramework) GeneratePrunableData(epoch iotago.EpochIndex, size int64 block := tpkg.RandProtocolBlock(&iotago.BasicBlock{ StrongParents: tpkg.SortedRandBlockIDs(1 + rand.Intn(iotago.BlockMaxParents)), Payload: &iotago.TaggedData{Data: make([]byte, 8192)}, - BurnedMana: 1000, + MaxBurnedMana: 1000, }, apiForEpoch, 0) modelBlock, err := model.BlockFromBlock(block) diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index 9b946801a..fca864f9a 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -65,10 +65,10 @@ func Test_TransitionAccount(t *testing.T) { accountInput, accountOutputs, accountWallets := ts.TransactionFramework.TransitionAccount( "Genesis:1", - testsuite.AddBlockIssuerKey(newGenesisOutputKey), + testsuite.WithAddBlockIssuerKey(newGenesisOutputKey), testsuite.WithBlockIssuerExpirySlot(1), ) - consumedInputs, equalOutputs, equalWallets := ts.TransactionFramework.CreateBasicOutputsEqually(2, "Genesis:0") + consumedInputs, equalOutputs, equalWallets := ts.TransactionFramework.CreateBasicOutputsEqually(4, "Genesis:0") tx1 := lo.PanicOnErr(ts.TransactionFramework.CreateTransactionWithOptions("TX1", append(accountWallets, equalWallets...), testsuite.WithAccountInput(accountInput, true), @@ -102,7 +102,7 @@ func Test_TransitionAccount(t *testing.T) { PreviousUpdatedTime: 0, PreviousExpirySlot: 1, NewExpirySlot: 1, - NewOutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(ts.TransactionFramework.Transaction("TX1").ID()), 0), + NewOutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(ts.TransactionFramework.SignedTransaction("TX1").ID()), 0), PreviousOutputID: genesisAccount.OutputID(), BlockIssuerKeysRemoved: iotago.NewBlockIssuerKeys(), BlockIssuerKeysAdded: iotago.NewBlockIssuerKeys(newGenesisOutputKey), @@ -111,7 +111,7 @@ func Test_TransitionAccount(t *testing.T) { ts.AssertAccountData(&accounts.AccountData{ ID: genesisAccountOutput.AccountID, Credits: accounts.NewBlockIssuanceCredits(iotago.BlockIssuanceCredits(123), 0), - OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(ts.TransactionFramework.Transaction("TX1").ID()), 0), + OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(ts.TransactionFramework.SignedTransaction("TX1").ID()), 0), BlockIssuerKeys: iotago.NewBlockIssuerKeys(oldGenesisOutputKey, newGenesisOutputKey), ExpirySlot: 1, }, ts.Nodes()...) @@ -127,16 +127,8 @@ func Test_TransitionAccount(t *testing.T) { &iotago.StateControllerAddressUnlockCondition{Address: ts.TransactionFramework.DefaultAddress()}, &iotago.GovernorAddressUnlockCondition{Address: ts.TransactionFramework.DefaultAddress()}, }), - testsuite.WithBlockIssuerFeature(&iotago.BlockIssuerFeature{ - BlockIssuerKeys: iotago.NewBlockIssuerKeys(newAccountBlockIssuerKey), - ExpirySlot: newAccountExpirySlot, - }), - testsuite.WithStakingFeature(&iotago.StakingFeature{ - StakedAmount: 10000, - FixedCost: 421, - StartEpoch: 0, - EndEpoch: 10, - }), + testsuite.WithBlockIssuerFeature(iotago.BlockIssuerKeys{newAccountBlockIssuerKey}, newAccountExpirySlot), + testsuite.WithStakingFeature(10000, 421, 0, 10), ) destroyedAccountInput, destructionOutputs, destroyWallets := ts.TransactionFramework.DestroyAccount("TX1:0") @@ -169,7 +161,7 @@ func Test_TransitionAccount(t *testing.T) { NewExpirySlot: 0, PreviousExpirySlot: 1, NewOutputID: iotago.EmptyOutputID, - PreviousOutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(ts.TransactionFramework.Transaction("TX1").ID()), 0), + PreviousOutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(ts.TransactionFramework.SignedTransaction("TX1").ID()), 0), BlockIssuerKeysAdded: iotago.NewBlockIssuerKeys(), BlockIssuerKeysRemoved: iotago.NewBlockIssuerKeys(oldGenesisOutputKey, newGenesisOutputKey), ValidatorStakeChange: 0, @@ -276,7 +268,7 @@ func Test_TransitionAccount(t *testing.T) { block4 := ts.IssueBlockAtSlotWithOptions("block4", block4Slot, node1.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment(), node1, tx4, blockfactory.WithStrongParents(latestParent.ID())) - _ = ts.CommitUntilSlot(block4Slot, activeNodes, block4) + latestParent = ts.CommitUntilSlot(block4Slot, activeNodes, block4) ts.AssertAccountDiff(newAccountOutput.AccountID, block4Slot, &model.AccountDiff{ BICChange: 0, @@ -303,6 +295,91 @@ func Test_TransitionAccount(t *testing.T) { ValidatorStake: 10000, }, ts.Nodes()...) + // CREATE IMPLICIT ACCOUNT FROM BASIC UTXO + inputForImplicitAccount, outputsForImplicitAccount, implicitAccountAddress, implicitWallet := ts.TransactionFramework.CreateImplicitAccountFromInput("TX1:3") + + tx5 := lo.PanicOnErr(ts.TransactionFramework.CreateTransactionWithOptions("TX5", implicitWallet, + testsuite.WithInputs(inputForImplicitAccount), + testsuite.WithOutputs(outputsForImplicitAccount), + )) + + implicitAccountOutput := ts.TransactionFramework.Output("TX5:0") + implicitAccountOutputID := implicitAccountOutput.OutputID() + implicitAccountID := iotago.AccountIDFromOutputID(implicitAccountOutputID) + + slotIndexBlock5 := latestParent.ID().Index() + + block5 := ts.IssueBlockAtSlotWithOptions("block5", slotIndexBlock5, node1.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment(), node1, tx5, blockfactory.WithStrongParents(latestParent.ID())) + + latestParent = ts.CommitUntilSlot(slotIndexBlock5, activeNodes, block5) + + var implicitBlockIssuerKey iotago.BlockIssuerKey = iotago.Ed25519PublicKeyHashBlockIssuerKeyFromImplicitAccountCreationAddress(implicitAccountAddress) + + ts.AssertAccountData(&accounts.AccountData{ + ID: implicitAccountID, + Credits: accounts.NewBlockIssuanceCredits(0, slotIndexBlock5), + ExpirySlot: iotago.MaxSlotIndex, + OutputID: implicitAccountOutputID, + BlockIssuerKeys: iotago.NewBlockIssuerKeys(implicitBlockIssuerKey), + }, ts.Nodes()...) + + // TRANSITION IMPLICIT ACCOUNT TO ACCOUNT OUTPUT + + fullAccountBlockIssuerKey := utils.RandBlockIssuerKey() + + inputForImplicitAccountTransition, outputsForImplicitAccountTransition, fullAccountWallet := ts.TransactionFramework.TransitionImplicitAccountToAccountOutput( + "TX5:0", + testsuite.WithBlockIssuerFeature( + iotago.BlockIssuerKeys{fullAccountBlockIssuerKey}, + iotago.MaxSlotIndex, + ), + ) + + tx6 := lo.PanicOnErr(ts.TransactionFramework.CreateTransactionWithOptions("TX6", fullAccountWallet, + testsuite.WithContextInputs(iotago.TxEssenceContextInputs{ + &iotago.BlockIssuanceCreditInput{ + AccountID: implicitAccountID, + }, + &iotago.CommitmentInput{ + CommitmentID: node1.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment().MustID(), + }, + }), + testsuite.WithInputs(inputForImplicitAccountTransition), + testsuite.WithOutputs(outputsForImplicitAccountTransition), + testsuite.WithSlotCreated(slotIndexBlock5), + )) + + slotIndexBlock6 := latestParent.ID().Index() + + block6 := ts.IssueBlockAtSlotWithOptions("block6", slotIndexBlock6, node1.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment(), node1, tx6, blockfactory.WithStrongParents(latestParent.ID())) + + latestParent = ts.CommitUntilSlot(slotIndexBlock6, activeNodes, block6) + + fullAccountOutputID := ts.TransactionFramework.Output("TX6:0").OutputID() + + ts.AssertAccountDiff(implicitAccountID, slotIndexBlock6, &model.AccountDiff{ + BICChange: 0, + PreviousUpdatedTime: 0, + NewOutputID: fullAccountOutputID, + PreviousOutputID: implicitAccountOutputID, + PreviousExpirySlot: iotago.MaxSlotIndex, + NewExpirySlot: iotago.MaxSlotIndex, + BlockIssuerKeysAdded: iotago.BlockIssuerKeys{fullAccountBlockIssuerKey}, + BlockIssuerKeysRemoved: iotago.BlockIssuerKeys{implicitBlockIssuerKey}, + ValidatorStakeChange: 0, + StakeEndEpochChange: 0, + FixedCostChange: 0, + DelegationStakeChange: 0, + }, false, ts.Nodes()...) + + ts.AssertAccountData(&accounts.AccountData{ + ID: implicitAccountID, + Credits: accounts.NewBlockIssuanceCredits(0, slotIndexBlock5), + ExpirySlot: iotago.MaxSlotIndex, + OutputID: fullAccountOutputID, + BlockIssuerKeys: iotago.NewBlockIssuerKeys(fullAccountBlockIssuerKey), + }, ts.Nodes()...) + ts.Wait(ts.Nodes()...) } diff --git a/pkg/tests/booker_test.go b/pkg/tests/booker_test.go index 15e48560b..da743259b 100644 --- a/pkg/tests/booker_test.go +++ b/pkg/tests/booker_test.go @@ -26,24 +26,24 @@ func Test_IssuingTransactionsOutOfOrder(t *testing.T) { ts.IssuePayloadWithOptions("block1", node1, tx2) - ts.AssertTransactionsExist(ts.TransactionFramework.Transactions("tx2"), true, node1) - ts.AssertTransactionsExist(ts.TransactionFramework.Transactions("tx1"), false, node1) + ts.AssertTransactionsExist(ts.TransactionFramework.SignedTransactions("tx2"), true, node1) + ts.AssertTransactionsExist(ts.TransactionFramework.SignedTransactions("tx1"), false, node1) - ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.Transactions("tx2"), false, node1) + ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.SignedTransactions("tx2"), false, node1) // make sure that the block is not booked ts.IssuePayloadWithOptions("block2", node1, tx1) - ts.AssertTransactionsExist(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1) - ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1) + ts.AssertTransactionsExist(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1) + ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1) ts.AssertBlocksInCacheConflicts(map[*blocks.Block][]string{ ts.Block("block1"): {"tx2"}, ts.Block("block2"): {"tx1"}, }, node1) - ts.AssertTransactionInCacheConflicts(map[*iotago.Transaction][]string{ - ts.TransactionFramework.Transaction("tx2"): {"tx2"}, - ts.TransactionFramework.Transaction("tx1"): {"tx1"}, + ts.AssertTransactionInCacheConflicts(map[*iotago.SignedTransaction][]string{ + ts.TransactionFramework.SignedTransaction("tx2"): {"tx2"}, + ts.TransactionFramework.SignedTransaction("tx1"): {"tx1"}, }, node1) } @@ -69,17 +69,17 @@ func Test_DoubleSpend(t *testing.T) { ts.IssuePayloadWithOptions("block1", node1, tx1, blockfactory.WithStrongParents(ts.BlockID("Genesis"))) ts.IssuePayloadWithOptions("block2", node1, tx2, blockfactory.WithStrongParents(ts.BlockID("Genesis"))) - ts.AssertTransactionsExist(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1, node2) - ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1, node2) - ts.AssertTransactionsInCachePending(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1, node2) + ts.AssertTransactionsExist(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1, node2) + ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1, node2) + ts.AssertTransactionsInCachePending(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1, node2) ts.AssertBlocksInCacheConflicts(map[*blocks.Block][]string{ ts.Block("block1"): {"tx1"}, ts.Block("block2"): {"tx2"}, }, node1, node2) - ts.AssertTransactionInCacheConflicts(map[*iotago.Transaction][]string{ - ts.TransactionFramework.Transaction("tx2"): {"tx2"}, - ts.TransactionFramework.Transaction("tx1"): {"tx1"}, + ts.AssertTransactionInCacheConflicts(map[*iotago.SignedTransaction][]string{ + ts.TransactionFramework.SignedTransaction("tx2"): {"tx2"}, + ts.TransactionFramework.SignedTransaction("tx1"): {"tx1"}, }, node1, node2) } @@ -92,14 +92,14 @@ func Test_DoubleSpend(t *testing.T) { ts.Block("block3"): {"tx1"}, ts.Block("block4"): {"tx2"}, }, node1, node2) - ts.AssertTransactionsInCachePending(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1, node2) + ts.AssertTransactionsInCachePending(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1, node2) } // Issue an invalid block and assert that its vote is not cast. { ts.IssueValidationBlock("block5", node2, blockfactory.WithStrongParents(ts.BlockIDs("block3", "block4")...)) - ts.AssertTransactionsInCachePending(ts.TransactionFramework.Transactions("tx1", "tx2"), true, node1, node2) + ts.AssertTransactionsInCachePending(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, node1, node2) } // Issue valid blocks that resolve the conflict. @@ -110,8 +110,8 @@ func Test_DoubleSpend(t *testing.T) { ts.AssertBlocksInCacheConflicts(map[*blocks.Block][]string{ ts.Block("block6"): {"tx2"}, }, node1, node2) - ts.AssertTransactionsInCacheAccepted(ts.TransactionFramework.Transactions("tx2"), true, node1, node2) - ts.AssertTransactionsInCacheRejected(ts.TransactionFramework.Transactions("tx1"), true, node1, node2) + ts.AssertTransactionsInCacheAccepted(ts.TransactionFramework.SignedTransactions("tx2"), true, node1, node2) + ts.AssertTransactionsInCacheRejected(ts.TransactionFramework.SignedTransactions("tx1"), true, node1, node2) } } @@ -148,8 +148,8 @@ func Test_MultipleAttachments(t *testing.T) { ts.Block("A.2"): {"tx1"}, ts.Block("B.2"): {"tx1"}, }), ts.Nodes()...) - ts.AssertTransactionInCacheConflicts(map[*iotago.Transaction][]string{ - ts.TransactionFramework.Transaction("tx1"): {"tx1"}, + ts.AssertTransactionInCacheConflicts(map[*iotago.SignedTransaction][]string{ + ts.TransactionFramework.SignedTransaction("tx1"): {"tx1"}, }, ts.Nodes()...) ts.AssertConflictsInCacheAcceptanceState([]string{"tx1"}, acceptance.Accepted, ts.Nodes()...) } @@ -171,8 +171,8 @@ func Test_MultipleAttachments(t *testing.T) { ts.AssertBlocksInCachePreAccepted(ts.Blocks("B.4", "A.5"), false, ts.Nodes()...) ts.AssertBlocksInCacheAccepted(ts.Blocks("A.3"), true, ts.Nodes()...) - ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.Transactions("tx1", "tx2"), true, ts.Nodes()...) - ts.AssertTransactionsInCachePending(ts.TransactionFramework.Transactions("tx1", "tx2"), true, ts.Nodes()...) + ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, ts.Nodes()...) + ts.AssertTransactionsInCachePending(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, ts.Nodes()...) ts.AssertBlocksInCacheConflicts(lo.MergeMaps(blocksConflicts, map[*blocks.Block][]string{ ts.Block("A.3"): {"tx2"}, @@ -181,9 +181,9 @@ func Test_MultipleAttachments(t *testing.T) { ts.Block("A.5"): {}, ts.Block("B.4"): {}, }), ts.Nodes()...) - ts.AssertTransactionInCacheConflicts(map[*iotago.Transaction][]string{ - ts.TransactionFramework.Transaction("tx1"): {"tx1"}, - ts.TransactionFramework.Transaction("tx2"): {"tx2"}, + ts.AssertTransactionInCacheConflicts(map[*iotago.SignedTransaction][]string{ + ts.TransactionFramework.SignedTransaction("tx1"): {"tx1"}, + ts.TransactionFramework.SignedTransaction("tx2"): {"tx2"}, }, nodeA, nodeB) ts.AssertConflictsInCacheAcceptanceState([]string{"tx1", "tx2"}, acceptance.Accepted, ts.Nodes()...) } @@ -200,9 +200,9 @@ func Test_MultipleAttachments(t *testing.T) { ts.AssertBlocksInCacheAccepted(ts.Blocks("A.1", "B.1"), true, ts.Nodes()...) ts.AssertBlocksInCachePreAccepted(ts.Blocks("A.7", "B.6"), false, ts.Nodes()...) - ts.AssertTransactionsExist(ts.TransactionFramework.Transactions("tx1", "tx2"), true, ts.Nodes()...) - ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.Transactions("tx1", "tx2"), true, ts.Nodes()...) - ts.AssertTransactionsInCacheAccepted(ts.TransactionFramework.Transactions("tx1", "tx2"), true, ts.Nodes()...) + ts.AssertTransactionsExist(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, ts.Nodes()...) + ts.AssertTransactionsInCacheBooked(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, ts.Nodes()...) + ts.AssertTransactionsInCacheAccepted(ts.TransactionFramework.SignedTransactions("tx1", "tx2"), true, ts.Nodes()...) ts.AssertBlocksInCacheConflicts(lo.MergeMaps(blocksConflicts, map[*blocks.Block][]string{ ts.Block("A.6"): {}, @@ -211,9 +211,9 @@ func Test_MultipleAttachments(t *testing.T) { ts.Block("B.6"): {}, }), ts.Nodes()...) - ts.AssertTransactionInCacheConflicts(map[*iotago.Transaction][]string{ - ts.TransactionFramework.Transaction("tx1"): {"tx1"}, - ts.TransactionFramework.Transaction("tx2"): {"tx2"}, + ts.AssertTransactionInCacheConflicts(map[*iotago.SignedTransaction][]string{ + ts.TransactionFramework.SignedTransaction("tx1"): {"tx1"}, + ts.TransactionFramework.SignedTransaction("tx2"): {"tx2"}, }, nodeA, nodeB) ts.AssertConflictsInCacheAcceptanceState([]string{"tx1", "tx2"}, acceptance.Accepted, nodeA, nodeB) } diff --git a/pkg/tests/confirmation_state_test.go b/pkg/tests/confirmation_state_test.go index f7eb5e866..55a7031bb 100644 --- a/pkg/tests/confirmation_state_test.go +++ b/pkg/tests/confirmation_state_test.go @@ -17,9 +17,10 @@ import ( func TestConfirmationFlags(t *testing.T) { ts := testsuite.NewTestSuite(t, - testsuite.WithLivenessThreshold(1), // TODO: remove this opt and use a proper value when refactoring the test with scheduler - testsuite.WithMinCommittableAge(10), // TODO: remove this opt and use a proper value when refactoring the test with scheduler - testsuite.WithMaxCommittableAge(20), // TODO: remove this opt and use a proper value when refactoring the test with scheduler + testsuite.WithLivenessThresholdLowerBound(10), // TODO: remove this opt and use a proper value when refactoring the test with scheduler + testsuite.WithLivenessThresholdUpperBound(10), // TODO: remove this opt and use a proper value when refactoring the test with scheduler + testsuite.WithMinCommittableAge(10), // TODO: remove this opt and use a proper value when refactoring the test with scheduler + testsuite.WithMaxCommittableAge(20), // TODO: remove this opt and use a proper value when refactoring the test with scheduler testsuite.WithGenesisTimestampOffset(100*10), ) defer ts.Shutdown() diff --git a/pkg/tests/protocol_engine_rollback_test.go b/pkg/tests/protocol_engine_rollback_test.go index 940c72fef..79381bf1f 100644 --- a/pkg/tests/protocol_engine_rollback_test.go +++ b/pkg/tests/protocol_engine_rollback_test.go @@ -1,781 +1,785 @@ package tests -//import ( -// "fmt" -// "testing" -// "time" -// -// "github.com/stretchr/testify/require" -// -// "github.com/iotaledger/hive.go/core/eventticker" -// "github.com/iotaledger/hive.go/lo" -// "github.com/iotaledger/hive.go/runtime/module" -// "github.com/iotaledger/hive.go/runtime/options" -// "github.com/iotaledger/iota-core/pkg/core/account" -// "github.com/iotaledger/iota-core/pkg/protocol" -// "github.com/iotaledger/iota-core/pkg/protocol/chainmanager" -// "github.com/iotaledger/iota-core/pkg/protocol/engine" -// "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" -// "github.com/iotaledger/iota-core/pkg/protocol/sybilprotection/seatmanager" -// "github.com/iotaledger/iota-core/pkg/protocol/sybilprotection/seatmanager/mock" -// "github.com/iotaledger/iota-core/pkg/protocol/sybilprotection/sybilprotectionv1" -// "github.com/iotaledger/iota-core/pkg/storage" -// "github.com/iotaledger/iota-core/pkg/testsuite" -// mock2 "github.com/iotaledger/iota-core/pkg/testsuite/mock" -// iotago "github.com/iotaledger/iota.go/v4" -//) -// -//func TestProtocol_EngineRollbackFinalization(t *testing.T) { -// ts := testsuite.NewTestSuite(t, -// testsuite.WithLivenessThreshold(1), -// testsuite.WithMinCommittableAge(2), -// testsuite.WithMaxCommittableAge(3), -// testsuite.WithEpochNearingThreshold(5), -// testsuite.WithSlotsPerEpochExponent(3), -// testsuite.WithGenesisTimestampOffset(1000*10), -// -// testsuite.WithWaitFor(15*time.Second), -// ) -// defer ts.Shutdown() -// -// node0 := ts.AddValidatorNode("node0") -// node1 := ts.AddValidatorNode("node1") -// node2 := ts.AddValidatorNode("node2") -// node3 := ts.AddValidatorNode("node3") -// -// poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { -// return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { -// poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) -// -// for _, node := range []*mock2.Node{node0, node1, node2, node3} { -// if node.Validator { -// poa.AddAccount(node.AccountID, node.Name) -// } -// } -// poa.SetOnline("node0", "node1", "node2", "node3") -// -// return poa -// }) -// } -// -// nodeOptions := make(map[string][]options.Option[protocol.Protocol]) -// for _, node := range ts.Nodes() { -// nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ -// protocol.WithChainManagerOptions( -// chainmanager.WithCommitmentRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), -// ), -// ), -// protocol.WithSybilProtectionProvider( -// sybilprotectionv1.NewProvider( -// sybilprotectionv1.WithSeatManagerProvider( -// poaProvider(), -// ), -// ), -// ), -// protocol.WithEngineOptions( -// engine.WithBlockRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), -// ), -// ), -// protocol.WithStorageOptions( -// storage.WithPruningDelay(20), -// ), -// } -// } -// -// ts.Run(false, nodeOptions) -// -// // Verify that nodes have the expected states. -// -// expectedCommittee := []iotago.AccountID{ -// node0.AccountID, -// node1.AccountID, -// node2.AccountID, -// node3.AccountID, -// } -// expectedOnlineCommitteeFull := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), -// } -// -// for _, node := range ts.Nodes() { -// node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") -// } -// -// { -// genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) -// genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithSnapshotImported(true), -// testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), -// testsuite.WithLatestCommitment(genesisCommitment), -// testsuite.WithLatestFinalizedSlot(0), -// testsuite.WithChainID(genesisCommitment.MustID()), -// testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), -// -// testsuite.WithSybilProtectionCommittee(0, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(0), -// testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), -// testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), -// ) -// } -// -// // Issue up to slot 11 - just before committee selection for the next epoch. -// // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(9), -// testsuite.WithEqualStoredCommitmentAtIndex(9), -// testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(9, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(9), -// ) -// -// for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { -// var attestationBlocks []*blocks.Block -// for _, node := range ts.Nodes() { -// if node.Validator { -// attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) -// } -// } -// ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) -// } -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15, 16}, 4, "P0:11.3", ts.Nodes(), true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(13), -// testsuite.WithLatestCommitmentSlotIndex(14), -// testsuite.WithEqualStoredCommitmentAtIndex(14), -// testsuite.WithLatestCommitmentCumulativeWeight(48), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(14, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(14), -// ) -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(13) -// require.NoError(t, err) -// -// // Assert state of the forked engine after rollback. -// { -// require.EqualValues(t, 13, newEngine.Storage.Settings().LatestCommitment().Slot()) -// require.EqualValues(t, 13, newEngine.Storage.Settings().LatestFinalizedSlot()) -// require.EqualValues(t, 13, newEngine.EvictionState.LastEvictedSlot()) -// -// for epoch := 0; epoch <= 2; epoch++ { -// committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) -// require.NoError(t, err) -// require.Len(t, committeeEpoch.IDs(), 4) -// } -// -// // Commmittee for the future epoch does not exist. -// committeeEpoch3, err := newEngine.Storage.Committee().Load(3) -// require.NoError(t, err) -// require.Nil(t, committeeEpoch3) -// -// for slot := 1; slot <= 13; slot++ { -// copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) -// } -// -// // Commitment for the first slot after the fork does not exist. -// _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(14)) -// require.Error(t, err) -// } -//} -// -//func TestProtocol_EngineRollbackNoFinalization(t *testing.T) { -// ts := testsuite.NewTestSuite(t, -// testsuite.WithLivenessThreshold(1), -// testsuite.WithMinCommittableAge(2), -// testsuite.WithMaxCommittableAge(3), -// testsuite.WithEpochNearingThreshold(5), -// testsuite.WithSlotsPerEpochExponent(3), -// testsuite.WithGenesisTimestampOffset(1000*10), -// -// testsuite.WithWaitFor(15*time.Second), -// ) -// defer ts.Shutdown() -// -// node0 := ts.AddValidatorNode("node0") -// node1 := ts.AddValidatorNode("node1") -// node2 := ts.AddValidatorNode("node2") -// node3 := ts.AddValidatorNode("node3") -// -// poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { -// return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { -// poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) -// -// for _, node := range []*mock2.Node{node0, node1, node2, node3} { -// if node.Validator { -// poa.AddAccount(node.AccountID, node.Name) -// } -// } -// poa.SetOnline("node0", "node1", "node2", "node3") -// -// return poa -// }) -// } -// -// nodeOptions := make(map[string][]options.Option[protocol.Protocol]) -// for _, node := range ts.Nodes() { -// nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ -// protocol.WithChainManagerOptions( -// chainmanager.WithCommitmentRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), -// ), -// ), -// protocol.WithSybilProtectionProvider( -// sybilprotectionv1.NewProvider( -// sybilprotectionv1.WithSeatManagerProvider( -// poaProvider(), -// ), -// ), -// ), -// protocol.WithEngineOptions( -// engine.WithBlockRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), -// ), -// ), -// protocol.WithStorageOptions( -// storage.WithPruningDelay(20), -// ), -// } -// } -// -// ts.Run(false, nodeOptions) -// -// // Verify that nodes have the expected states. -// -// expectedCommittee := []iotago.AccountID{ -// node0.AccountID, -// node1.AccountID, -// node2.AccountID, -// node3.AccountID, -// } -// expectedOnlineCommitteeFull := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), -// } -// -// expectedOnlineCommitteeHalf := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// } -// -// for _, node := range ts.Nodes() { -// node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") -// } -// -// { -// genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) -// genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithSnapshotImported(true), -// testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), -// testsuite.WithLatestCommitment(genesisCommitment), -// testsuite.WithLatestFinalizedSlot(0), -// testsuite.WithChainID(genesisCommitment.MustID()), -// testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), -// -// testsuite.WithSybilProtectionCommittee(0, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(0), -// testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), -// testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), -// ) -// } -// -// // Issue up to slot 11 - just before committee selection for the next epoch. -// // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(9), -// testsuite.WithEqualStoredCommitmentAtIndex(9), -// testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(9, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(9), -// ) -// -// for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { -// var attestationBlocks []*blocks.Block -// for _, node := range ts.Nodes() { -// if node.Validator { -// attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) -// } -// } -// ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) -// } -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// // Update online committee. -// for _, node := range ts.Nodes() { -// manualPOA := node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA) -// manualPOA.SetOnline("node0", "node1") -// manualPOA.SetOffline("node2", "node3") -// } -// -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15, 16}, 4, "P0:11.3", []*mock2.Node{node0, node1}, true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(14), -// testsuite.WithEqualStoredCommitmentAtIndex(14), -// testsuite.WithLatestCommitmentCumulativeWeight(44), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(14, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeHalf...), -// testsuite.WithEvictedSlot(14), -// ) -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(13) -// require.NoError(t, err) -// -// // Assert state of the forked engine after rollback. -// { -// require.EqualValues(t, 13, newEngine.Storage.Settings().LatestCommitment().Slot()) -// require.EqualValues(t, 8, newEngine.Storage.Settings().LatestFinalizedSlot()) -// require.EqualValues(t, 13, newEngine.EvictionState.LastEvictedSlot()) -// -// for epoch := 0; epoch <= 2; epoch++ { -// committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) -// require.NoError(t, err) -// require.Len(t, committeeEpoch.IDs(), 4) -// } -// -// // Commmittee for the future epoch does not exist. -// committeeEpoch3, err := newEngine.Storage.Committee().Load(3) -// require.NoError(t, err) -// require.Nil(t, committeeEpoch3) -// -// for slot := 1; slot <= 13; slot++ { -// copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) -// } -// -// // Commitment for the first slot after the fork does not exist. -// _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(14)) -// require.Error(t, err) -// } -//} -// -//func TestProtocol_EngineRollbackNoFinalizationLastSlot(t *testing.T) { -// ts := testsuite.NewTestSuite(t, -// testsuite.WithLivenessThreshold(1), -// testsuite.WithMinCommittableAge(2), -// testsuite.WithMaxCommittableAge(3), -// testsuite.WithEpochNearingThreshold(5), -// testsuite.WithSlotsPerEpochExponent(3), -// testsuite.WithGenesisTimestampOffset(1000*10), -// -// testsuite.WithWaitFor(15*time.Second), -// ) -// defer ts.Shutdown() -// -// node0 := ts.AddValidatorNode("node0") -// node1 := ts.AddValidatorNode("node1") -// node2 := ts.AddValidatorNode("node2") -// node3 := ts.AddValidatorNode("node3") -// -// poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { -// return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { -// poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) -// -// for _, node := range []*mock2.Node{node0, node1, node2, node3} { -// if node.Validator { -// poa.AddAccount(node.AccountID, node.Name) -// } -// } -// poa.SetOnline("node0", "node1", "node2", "node3") -// -// return poa -// }) -// } -// -// nodeOptions := make(map[string][]options.Option[protocol.Protocol]) -// for _, node := range ts.Nodes() { -// nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ -// protocol.WithChainManagerOptions( -// chainmanager.WithCommitmentRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), -// ), -// ), -// protocol.WithSybilProtectionProvider( -// sybilprotectionv1.NewProvider( -// sybilprotectionv1.WithSeatManagerProvider( -// poaProvider(), -// ), -// ), -// ), -// protocol.WithEngineOptions( -// engine.WithBlockRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), -// ), -// ), -// protocol.WithStorageOptions( -// storage.WithPruningDelay(20), -// ), -// } -// } -// -// ts.Run(false, nodeOptions) -// -// // Verify that nodes have the expected states. -// -// expectedCommittee := []iotago.AccountID{ -// node0.AccountID, -// node1.AccountID, -// node2.AccountID, -// node3.AccountID, -// } -// expectedOnlineCommitteeFull := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), -// } -// -// expectedOnlineCommitteeHalf := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// } -// -// for _, node := range ts.Nodes() { -// node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") -// } -// -// { -// genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) -// genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithSnapshotImported(true), -// testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), -// testsuite.WithLatestCommitment(genesisCommitment), -// testsuite.WithLatestFinalizedSlot(0), -// testsuite.WithChainID(genesisCommitment.MustID()), -// testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), -// -// testsuite.WithSybilProtectionCommittee(0, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(0), -// testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), -// testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), -// ) -// } -// -// // Issue up to slot 11 - just before committee selection for the next epoch. -// // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(9), -// testsuite.WithEqualStoredCommitmentAtIndex(9), -// testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(9, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(9), -// ) -// -// for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { -// var attestationBlocks []*blocks.Block -// for _, node := range ts.Nodes() { -// if node.Validator { -// attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) -// } -// } -// ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) -// } -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// // Update online committee. -// for _, node := range ts.Nodes() { -// manualPOA := node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA) -// manualPOA.SetOnline("node0", "node1") -// manualPOA.SetOffline("node2", "node3") -// } -// -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15, 16, 17, 18, 19}, 4, "P0:11.3", []*mock2.Node{node0, node1}, true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(17), -// testsuite.WithEqualStoredCommitmentAtIndex(17), -// testsuite.WithLatestCommitmentCumulativeWeight(50), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(17, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeHalf...), -// testsuite.WithEvictedSlot(17), -// ) -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(15) -// require.NoError(t, err) -// -// // Assert state of the forked engine after rollback. -// { -// require.EqualValues(t, 15, newEngine.Storage.Settings().LatestCommitment().Slot()) -// require.EqualValues(t, 8, newEngine.Storage.Settings().LatestFinalizedSlot()) -// require.EqualValues(t, 15, newEngine.EvictionState.LastEvictedSlot()) -// -// for epoch := 0; epoch <= 2; epoch++ { -// committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) -// require.NoError(t, err) -// require.Len(t, committeeEpoch.IDs(), 4) -// } -// -// // Commmittee for the future epoch does not exist. -// committeeEpoch3, err := newEngine.Storage.Committee().Load(3) -// require.NoError(t, err) -// require.Nil(t, committeeEpoch3) -// -// for slot := 1; slot <= 15; slot++ { -// copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) -// } -// -// // Commitment for the first slot after the fork does not exist. -// _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(16)) -// require.Error(t, err) -// } -//} -// -//func TestProtocol_EngineRollbackNoFinalizationBeforePointOfNoReturn(t *testing.T) { -// ts := testsuite.NewTestSuite(t, -// testsuite.WithLivenessThreshold(1), -// testsuite.WithMinCommittableAge(2), -// testsuite.WithMaxCommittableAge(3), -// testsuite.WithEpochNearingThreshold(5), -// testsuite.WithSlotsPerEpochExponent(3), -// testsuite.WithGenesisTimestampOffset(1000*10), -// -// testsuite.WithWaitFor(15*time.Second), -// ) -// defer ts.Shutdown() -// -// node0 := ts.AddValidatorNode("node0") -// node1 := ts.AddValidatorNode("node1") -// node2 := ts.AddValidatorNode("node2") -// node3 := ts.AddValidatorNode("node3") -// -// poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { -// return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { -// poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) -// -// for _, node := range []*mock2.Node{node0, node1, node2, node3} { -// if node.Validator { -// poa.AddAccount(node.AccountID, node.Name) -// } -// } -// poa.SetOnline("node0", "node1", "node2", "node3") -// -// return poa -// }) -// } -// -// nodeOptions := make(map[string][]options.Option[protocol.Protocol]) -// for _, node := range ts.Nodes() { -// nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ -// protocol.WithChainManagerOptions( -// chainmanager.WithCommitmentRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), -// ), -// ), -// protocol.WithSybilProtectionProvider( -// sybilprotectionv1.NewProvider( -// sybilprotectionv1.WithSeatManagerProvider( -// poaProvider(), -// ), -// ), -// ), -// protocol.WithEngineOptions( -// engine.WithBlockRequesterOptions( -// eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), -// eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), -// ), -// ), -// protocol.WithStorageOptions( -// storage.WithPruningDelay(20), -// ), -// } -// } -// -// ts.Run(false, nodeOptions) -// -// // Verify that nodes have the expected states. -// -// expectedCommittee := []iotago.AccountID{ -// node0.AccountID, -// node1.AccountID, -// node2.AccountID, -// node3.AccountID, -// } -// expectedOnlineCommitteeFull := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), -// } -// -// expectedOnlineCommitteeHalf := []account.SeatIndex{ -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), -// lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), -// } -// -// for _, node := range ts.Nodes() { -// node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") -// } -// -// { -// genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) -// genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithSnapshotImported(true), -// testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), -// testsuite.WithLatestCommitment(genesisCommitment), -// testsuite.WithLatestFinalizedSlot(0), -// testsuite.WithChainID(genesisCommitment.MustID()), -// testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), -// -// testsuite.WithSybilProtectionCommittee(0, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(0), -// testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), -// testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), -// ) -// } -// -// // Issue up to slot 11 - just before committee selection for the next epoch. -// // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(9), -// testsuite.WithEqualStoredCommitmentAtIndex(9), -// testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(9, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), -// testsuite.WithEvictedSlot(9), -// ) -// -// for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { -// var attestationBlocks []*blocks.Block -// for _, node := range ts.Nodes() { -// if node.Validator { -// attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) -// } -// } -// ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) -// } -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// // Update online committee. -// for _, node := range ts.Nodes() { -// manualPOA := node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA) -// manualPOA.SetOnline("node0", "node1") -// manualPOA.SetOffline("node2", "node3") -// } -// -// { -// ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15}, 4, "P0:11.3", []*mock2.Node{node0, node1}, true, nil) -// -// ts.AssertNodeState(ts.Nodes(), -// testsuite.WithLatestFinalizedSlot(8), -// testsuite.WithLatestCommitmentSlotIndex(13), -// testsuite.WithEqualStoredCommitmentAtIndex(13), -// testsuite.WithLatestCommitmentCumulativeWeight(42), // 7 for each slot starting from 4 -// testsuite.WithSybilProtectionCommittee(13, expectedCommittee), -// testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeHalf...), -// testsuite.WithEvictedSlot(13), -// ) -// -// ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) -// } -// -// newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(9) -// require.NoError(t, err) -// -// // Assert state of the forked engine after rollback. -// { -// require.EqualValues(t, 9, newEngine.Storage.Settings().LatestCommitment().Slot()) -// require.EqualValues(t, 8, newEngine.Storage.Settings().LatestFinalizedSlot()) -// require.EqualValues(t, 9, newEngine.EvictionState.LastEvictedSlot()) -// -// for epoch := 0; epoch <= 1; epoch++ { -// committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) -// require.NoError(t, err) -// require.Len(t, committeeEpoch.IDs(), 4) -// } -// -// // Commmittee for the future epoch does not exist. -// committeeEpoch2, err := newEngine.Storage.Committee().Load(2) -// require.NoError(t, err) -// require.Nil(t, committeeEpoch2) -// -// for slot := 1; slot <= 9; slot++ { -// copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) -// require.NoError(t, err) -// require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) -// } -// -// // Commitment for the first slot after the fork does not exist. -// _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(10)) -// require.Error(t, err) -// } -//} -// -//// TODO: test fork before point of no return (slot 12) -//// TODO: test fork on last slot of an epoch (slot 15) +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/iotaledger/hive.go/core/eventticker" + "github.com/iotaledger/hive.go/lo" + "github.com/iotaledger/hive.go/runtime/module" + "github.com/iotaledger/hive.go/runtime/options" + "github.com/iotaledger/iota-core/pkg/core/account" + "github.com/iotaledger/iota-core/pkg/protocol" + "github.com/iotaledger/iota-core/pkg/protocol/chainmanager" + "github.com/iotaledger/iota-core/pkg/protocol/engine" + "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" + "github.com/iotaledger/iota-core/pkg/protocol/sybilprotection/seatmanager" + "github.com/iotaledger/iota-core/pkg/protocol/sybilprotection/seatmanager/mock" + "github.com/iotaledger/iota-core/pkg/protocol/sybilprotection/sybilprotectionv1" + "github.com/iotaledger/iota-core/pkg/storage" + "github.com/iotaledger/iota-core/pkg/testsuite" + mock2 "github.com/iotaledger/iota-core/pkg/testsuite/mock" + iotago "github.com/iotaledger/iota.go/v4" +) + +func TestProtocol_EngineRollbackFinalization(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(3), + testsuite.WithEpochNearingThreshold(5), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(1000*10), + + testsuite.WithWaitFor(15*time.Second), + ) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + node1 := ts.AddValidatorNode("node1") + node2 := ts.AddValidatorNode("node2") + node3 := ts.AddValidatorNode("node3") + + poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { + return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { + poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) + + for _, node := range []*mock2.Node{node0, node1, node2, node3} { + if node.Validator { + poa.AddAccount(node.AccountID, node.Name) + } + } + poa.SetOnline("node0", "node1", "node2", "node3") + + return poa + }) + } + + nodeOptions := make(map[string][]options.Option[protocol.Protocol]) + for _, node := range ts.Nodes() { + nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ + protocol.WithChainManagerOptions( + chainmanager.WithCommitmentRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), + ), + ), + protocol.WithSybilProtectionProvider( + sybilprotectionv1.NewProvider( + sybilprotectionv1.WithSeatManagerProvider( + poaProvider(), + ), + ), + ), + protocol.WithEngineOptions( + engine.WithBlockRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), + ), + ), + protocol.WithStorageOptions( + storage.WithPruningDelay(20), + ), + } + } + + ts.Run(false, nodeOptions) + + // Verify that nodes have the expected states. + + expectedCommittee := []iotago.AccountID{ + node0.AccountID, + node1.AccountID, + node2.AccountID, + node3.AccountID, + } + expectedOnlineCommitteeFull := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), + } + + for _, node := range ts.Nodes() { + node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") + } + + { + genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) + genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost + ts.AssertNodeState(ts.Nodes(), + testsuite.WithSnapshotImported(true), + testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), + testsuite.WithLatestCommitment(genesisCommitment), + testsuite.WithLatestFinalizedSlot(0), + testsuite.WithChainID(genesisCommitment.MustID()), + testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), + + testsuite.WithSybilProtectionCommittee(0, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(0), + testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), + testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), + ) + } + + // Issue up to slot 11 - just before committee selection for the next epoch. + // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(9), + testsuite.WithEqualStoredCommitmentAtIndex(9), + testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(9, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(9), + ) + + for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { + var attestationBlocks []*blocks.Block + for _, node := range ts.Nodes() { + if node.Validator { + attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) + } + } + ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) + } + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15, 16}, 4, "P0:11.3", ts.Nodes(), true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(13), + testsuite.WithLatestCommitmentSlotIndex(14), + testsuite.WithEqualStoredCommitmentAtIndex(14), + testsuite.WithLatestCommitmentCumulativeWeight(48), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(14, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(14), + ) + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(13) + require.NoError(t, err) + + // Assert state of the forked engine after rollback. + { + require.EqualValues(t, 13, newEngine.Storage.Settings().LatestCommitment().Slot()) + require.EqualValues(t, 13, newEngine.Storage.Settings().LatestFinalizedSlot()) + require.EqualValues(t, 13, newEngine.EvictionState.LastEvictedSlot()) + + for epoch := 0; epoch <= 2; epoch++ { + committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) + require.NoError(t, err) + require.Len(t, committeeEpoch.IDs(), 4) + } + + // Commmittee for the future epoch does not exist. + committeeEpoch3, err := newEngine.Storage.Committee().Load(3) + require.NoError(t, err) + require.Nil(t, committeeEpoch3) + + for slot := 1; slot <= 13; slot++ { + copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) + } + + // Commitment for the first slot after the fork does not exist. + _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(14)) + require.Error(t, err) + } +} + +func TestProtocol_EngineRollbackNoFinalization(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(3), + testsuite.WithEpochNearingThreshold(5), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(1000*10), + + testsuite.WithWaitFor(15*time.Second), + ) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + node1 := ts.AddValidatorNode("node1") + node2 := ts.AddValidatorNode("node2") + node3 := ts.AddValidatorNode("node3") + + poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { + return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { + poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) + + for _, node := range []*mock2.Node{node0, node1, node2, node3} { + if node.Validator { + poa.AddAccount(node.AccountID, node.Name) + } + } + poa.SetOnline("node0", "node1", "node2", "node3") + + return poa + }) + } + + nodeOptions := make(map[string][]options.Option[protocol.Protocol]) + for _, node := range ts.Nodes() { + nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ + protocol.WithChainManagerOptions( + chainmanager.WithCommitmentRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), + ), + ), + protocol.WithSybilProtectionProvider( + sybilprotectionv1.NewProvider( + sybilprotectionv1.WithSeatManagerProvider( + poaProvider(), + ), + ), + ), + protocol.WithEngineOptions( + engine.WithBlockRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), + ), + ), + protocol.WithStorageOptions( + storage.WithPruningDelay(20), + ), + } + } + + ts.Run(false, nodeOptions) + + // Verify that nodes have the expected states. + + expectedCommittee := []iotago.AccountID{ + node0.AccountID, + node1.AccountID, + node2.AccountID, + node3.AccountID, + } + expectedOnlineCommitteeFull := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), + } + + expectedOnlineCommitteeHalf := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + } + + for _, node := range ts.Nodes() { + node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") + } + + { + genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) + genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost + ts.AssertNodeState(ts.Nodes(), + testsuite.WithSnapshotImported(true), + testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), + testsuite.WithLatestCommitment(genesisCommitment), + testsuite.WithLatestFinalizedSlot(0), + testsuite.WithChainID(genesisCommitment.MustID()), + testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), + + testsuite.WithSybilProtectionCommittee(0, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(0), + testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), + testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), + ) + } + + // Issue up to slot 11 - just before committee selection for the next epoch. + // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(9), + testsuite.WithEqualStoredCommitmentAtIndex(9), + testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(9, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(9), + ) + + for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { + var attestationBlocks []*blocks.Block + for _, node := range ts.Nodes() { + if node.Validator { + attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) + } + } + ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) + } + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + // Update online committee. + for _, node := range ts.Nodes() { + manualPOA := node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA) + manualPOA.SetOnline("node0", "node1") + manualPOA.SetOffline("node2", "node3") + } + + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15, 16}, 4, "P0:11.3", []*mock2.Node{node0, node1}, true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(14), + testsuite.WithEqualStoredCommitmentAtIndex(14), + testsuite.WithLatestCommitmentCumulativeWeight(44), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(14, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeHalf...), + testsuite.WithEvictedSlot(14), + ) + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(13) + require.NoError(t, err) + + // Assert state of the forked engine after rollback. + { + require.EqualValues(t, 13, newEngine.Storage.Settings().LatestCommitment().Slot()) + require.EqualValues(t, 8, newEngine.Storage.Settings().LatestFinalizedSlot()) + require.EqualValues(t, 13, newEngine.EvictionState.LastEvictedSlot()) + + for epoch := 0; epoch <= 2; epoch++ { + committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) + require.NoError(t, err) + require.Len(t, committeeEpoch.IDs(), 4) + } + + // Commmittee for the future epoch does not exist. + committeeEpoch3, err := newEngine.Storage.Committee().Load(3) + require.NoError(t, err) + require.Nil(t, committeeEpoch3) + + for slot := 1; slot <= 13; slot++ { + copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) + } + + // Commitment for the first slot after the fork does not exist. + _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(14)) + require.Error(t, err) + } +} + +func TestProtocol_EngineRollbackNoFinalizationLastSlot(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(3), + testsuite.WithEpochNearingThreshold(5), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(1000*10), + + testsuite.WithWaitFor(15*time.Second), + ) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + node1 := ts.AddValidatorNode("node1") + node2 := ts.AddValidatorNode("node2") + node3 := ts.AddValidatorNode("node3") + + poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { + return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { + poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) + + for _, node := range []*mock2.Node{node0, node1, node2, node3} { + if node.Validator { + poa.AddAccount(node.AccountID, node.Name) + } + } + poa.SetOnline("node0", "node1", "node2", "node3") + + return poa + }) + } + + nodeOptions := make(map[string][]options.Option[protocol.Protocol]) + for _, node := range ts.Nodes() { + nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ + protocol.WithChainManagerOptions( + chainmanager.WithCommitmentRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), + ), + ), + protocol.WithSybilProtectionProvider( + sybilprotectionv1.NewProvider( + sybilprotectionv1.WithSeatManagerProvider( + poaProvider(), + ), + ), + ), + protocol.WithEngineOptions( + engine.WithBlockRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), + ), + ), + protocol.WithStorageOptions( + storage.WithPruningDelay(20), + ), + } + } + + ts.Run(false, nodeOptions) + + // Verify that nodes have the expected states. + + expectedCommittee := []iotago.AccountID{ + node0.AccountID, + node1.AccountID, + node2.AccountID, + node3.AccountID, + } + expectedOnlineCommitteeFull := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), + } + + expectedOnlineCommitteeHalf := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + } + + for _, node := range ts.Nodes() { + node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") + } + + { + genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) + genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost + ts.AssertNodeState(ts.Nodes(), + testsuite.WithSnapshotImported(true), + testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), + testsuite.WithLatestCommitment(genesisCommitment), + testsuite.WithLatestFinalizedSlot(0), + testsuite.WithChainID(genesisCommitment.MustID()), + testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), + + testsuite.WithSybilProtectionCommittee(0, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(0), + testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), + testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), + ) + } + + // Issue up to slot 11 - just before committee selection for the next epoch. + // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(9), + testsuite.WithEqualStoredCommitmentAtIndex(9), + testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(9, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(9), + ) + + for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { + var attestationBlocks []*blocks.Block + for _, node := range ts.Nodes() { + if node.Validator { + attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) + } + } + ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) + } + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + // Update online committee. + for _, node := range ts.Nodes() { + manualPOA := node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA) + manualPOA.SetOnline("node0", "node1") + manualPOA.SetOffline("node2", "node3") + } + + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15, 16, 17, 18, 19}, 4, "P0:11.3", []*mock2.Node{node0, node1}, true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(17), + testsuite.WithEqualStoredCommitmentAtIndex(17), + testsuite.WithLatestCommitmentCumulativeWeight(50), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(17, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeHalf...), + testsuite.WithEvictedSlot(17), + ) + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(15) + require.NoError(t, err) + + // Assert state of the forked engine after rollback. + { + require.EqualValues(t, 15, newEngine.Storage.Settings().LatestCommitment().Slot()) + require.EqualValues(t, 8, newEngine.Storage.Settings().LatestFinalizedSlot()) + require.EqualValues(t, 15, newEngine.EvictionState.LastEvictedSlot()) + + for epoch := 0; epoch <= 2; epoch++ { + committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) + require.NoError(t, err) + require.Len(t, committeeEpoch.IDs(), 4) + } + + // Commmittee for the future epoch does not exist. + committeeEpoch3, err := newEngine.Storage.Committee().Load(3) + require.NoError(t, err) + require.Nil(t, committeeEpoch3) + + for slot := 1; slot <= 15; slot++ { + copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) + } + + // Commitment for the first slot after the fork does not exist. + _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(16)) + require.Error(t, err) + } +} + +func TestProtocol_EngineRollbackNoFinalizationBeforePointOfNoReturn(t *testing.T) { + ts := testsuite.NewTestSuite(t, + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), + testsuite.WithMinCommittableAge(2), + testsuite.WithMaxCommittableAge(3), + testsuite.WithEpochNearingThreshold(5), + testsuite.WithSlotsPerEpochExponent(3), + testsuite.WithGenesisTimestampOffset(1000*10), + + testsuite.WithWaitFor(15*time.Second), + ) + defer ts.Shutdown() + + node0 := ts.AddValidatorNode("node0") + node1 := ts.AddValidatorNode("node1") + node2 := ts.AddValidatorNode("node2") + node3 := ts.AddValidatorNode("node3") + + poaProvider := func() module.Provider[*engine.Engine, seatmanager.SeatManager] { + return module.Provide(func(e *engine.Engine) seatmanager.SeatManager { + poa := mock.NewManualPOAProvider()(e).(*mock.ManualPOA) + + for _, node := range []*mock2.Node{node0, node1, node2, node3} { + if node.Validator { + poa.AddAccount(node.AccountID, node.Name) + } + } + poa.SetOnline("node0", "node1", "node2", "node3") + + return poa + }) + } + + nodeOptions := make(map[string][]options.Option[protocol.Protocol]) + for _, node := range ts.Nodes() { + nodeOptions[node.Name] = []options.Option[protocol.Protocol]{ + protocol.WithChainManagerOptions( + chainmanager.WithCommitmentRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.CommitmentID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.CommitmentID](500*time.Millisecond), + ), + ), + protocol.WithSybilProtectionProvider( + sybilprotectionv1.NewProvider( + sybilprotectionv1.WithSeatManagerProvider( + poaProvider(), + ), + ), + ), + protocol.WithEngineOptions( + engine.WithBlockRequesterOptions( + eventticker.RetryInterval[iotago.SlotIndex, iotago.BlockID](1*time.Second), + eventticker.RetryJitter[iotago.SlotIndex, iotago.BlockID](500*time.Millisecond), + ), + ), + protocol.WithStorageOptions( + storage.WithPruningDelay(20), + ), + } + } + + ts.Run(false, nodeOptions) + + // Verify that nodes have the expected states. + + expectedCommittee := []iotago.AccountID{ + node0.AccountID, + node1.AccountID, + node2.AccountID, + node3.AccountID, + } + expectedOnlineCommitteeFull := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node2.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node3.AccountID)), + } + + expectedOnlineCommitteeHalf := []account.SeatIndex{ + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node0.AccountID)), + lo.Return1(node0.Protocol.MainEngineInstance().SybilProtection.SeatManager().Committee(1).GetSeat(node1.AccountID)), + } + + for _, node := range ts.Nodes() { + node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA).SetOnline("node0", "node1", "node2", "node3") + } + + { + genesisCommitment := iotago.NewEmptyCommitment(ts.API.ProtocolParameters().Version()) + genesisCommitment.ReferenceManaCost = ts.API.ProtocolParameters().CongestionControlParameters().MinReferenceManaCost + ts.AssertNodeState(ts.Nodes(), + testsuite.WithSnapshotImported(true), + testsuite.WithProtocolParameters(ts.API.ProtocolParameters()), + testsuite.WithLatestCommitment(genesisCommitment), + testsuite.WithLatestFinalizedSlot(0), + testsuite.WithChainID(genesisCommitment.MustID()), + testsuite.WithStorageCommitments([]*iotago.Commitment{genesisCommitment}), + + testsuite.WithSybilProtectionCommittee(0, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(0), + testsuite.WithActiveRootBlocks(ts.Blocks("Genesis")), + testsuite.WithStorageRootBlocks(ts.Blocks("Genesis")), + ) + } + + // Issue up to slot 11 - just before committee selection for the next epoch. + // Committee will be reused at slot 10 is finalized or slot 12 is committed, whichever happens first. + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 4, "Genesis", ts.Nodes(), true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(9), + testsuite.WithEqualStoredCommitmentAtIndex(9), + testsuite.WithLatestCommitmentCumulativeWeight(28), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(9, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeFull...), + testsuite.WithEvictedSlot(9), + ) + + for _, slot := range []iotago.SlotIndex{4, 5, 6, 7, 8, 9} { + var attestationBlocks []*blocks.Block + for _, node := range ts.Nodes() { + if node.Validator { + attestationBlocks = append(attestationBlocks, ts.Block(fmt.Sprintf("P0:%d.3-%s", slot, node.Name))) + } + } + ts.AssertAttestationsForSlot(slot, attestationBlocks, ts.Nodes()...) + } + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + // Update online committee. + for _, node := range ts.Nodes() { + manualPOA := node.Protocol.MainEngineInstance().SybilProtection.SeatManager().(*mock.ManualPOA) + manualPOA.SetOnline("node0", "node1") + manualPOA.SetOffline("node2", "node3") + } + + { + ts.IssueBlocksAtSlots("P0:", []iotago.SlotIndex{12, 13, 14, 15}, 4, "P0:11.3", []*mock2.Node{node0, node1}, true, nil) + + ts.AssertNodeState(ts.Nodes(), + testsuite.WithLatestFinalizedSlot(8), + testsuite.WithLatestCommitmentSlotIndex(13), + testsuite.WithEqualStoredCommitmentAtIndex(13), + testsuite.WithLatestCommitmentCumulativeWeight(42), // 7 for each slot starting from 4 + testsuite.WithSybilProtectionCommittee(13, expectedCommittee), + testsuite.WithSybilProtectionOnlineCommittee(expectedOnlineCommitteeHalf...), + testsuite.WithEvictedSlot(13), + ) + + ts.AssertBlocksExist(ts.BlocksWithPrefix("P0"), true, ts.Nodes()...) + } + + newEngine, err := node3.Protocol.EngineManager.ForkEngineAtSlot(9) + require.NoError(t, err) + + // Assert state of the forked engine after rollback. + { + require.EqualValues(t, 9, newEngine.Storage.Settings().LatestCommitment().Slot()) + require.EqualValues(t, 8, newEngine.Storage.Settings().LatestFinalizedSlot()) + require.EqualValues(t, 9, newEngine.EvictionState.LastEvictedSlot()) + + for epoch := 0; epoch <= 1; epoch++ { + committeeEpoch, err := newEngine.Storage.Committee().Load(iotago.EpochIndex(epoch)) + require.NoError(t, err) + require.Len(t, committeeEpoch.IDs(), 4) + } + + // Commmittee for the future epoch does not exist. + committeeEpoch2, err := newEngine.Storage.Committee().Load(2) + require.NoError(t, err) + require.Nil(t, committeeEpoch2) + + for slot := 1; slot <= 9; slot++ { + copiedCommitment, err := newEngine.Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + sourceCommitment, err := node1.Protocol.MainEngineInstance().Storage.Commitments().Load(iotago.SlotIndex(slot)) + require.NoError(t, err) + require.Equal(t, sourceCommitment.ID(), copiedCommitment.ID()) + } + + // Commitment for the first slot after the fork does not exist. + _, err = newEngine.Storage.Commitments().Load(iotago.SlotIndex(10)) + require.Error(t, err) + } +} + +// TODO: test fork before point of no return (slot 12) +// TODO: test fork on last slot of an epoch (slot 15) diff --git a/pkg/tests/protocol_engine_switching_test.go b/pkg/tests/protocol_engine_switching_test.go index 5bb958d92..d04fe00ec 100644 --- a/pkg/tests/protocol_engine_switching_test.go +++ b/pkg/tests/protocol_engine_switching_test.go @@ -28,7 +28,8 @@ import ( func TestProtocol_EngineSwitching(t *testing.T) { ts := testsuite.NewTestSuite(t, - testsuite.WithLivenessThreshold(1), + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), testsuite.WithMinCommittableAge(2), testsuite.WithMaxCommittableAge(4), testsuite.WithEpochNearingThreshold(2), diff --git a/pkg/tests/protocol_startup_test.go b/pkg/tests/protocol_startup_test.go index bccf280cd..03af7cc9b 100644 --- a/pkg/tests/protocol_startup_test.go +++ b/pkg/tests/protocol_startup_test.go @@ -22,7 +22,8 @@ import ( func Test_StartNodeFromSnapshotAndDisk(t *testing.T) { ts := testsuite.NewTestSuite(t, - testsuite.WithLivenessThreshold(1), + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), testsuite.WithMinCommittableAge(2), testsuite.WithMaxCommittableAge(4), testsuite.WithEpochNearingThreshold(2), diff --git a/pkg/tests/upgrade_signaling_test.go b/pkg/tests/upgrade_signaling_test.go index 072ac36b4..515a59d87 100644 --- a/pkg/tests/upgrade_signaling_test.go +++ b/pkg/tests/upgrade_signaling_test.go @@ -28,7 +28,8 @@ import ( func Test_Upgrade_Signaling(t *testing.T) { ts := testsuite.NewTestSuite(t, - testsuite.WithLivenessThreshold(1), + testsuite.WithLivenessThresholdLowerBound(10), + testsuite.WithLivenessThresholdUpperBound(10), testsuite.WithMinCommittableAge(2), testsuite.WithMaxCommittableAge(6), testsuite.WithEpochNearingThreshold(2), diff --git a/pkg/testsuite/blocks.go b/pkg/testsuite/blocks.go index 225df6b1e..11f65d693 100644 --- a/pkg/testsuite/blocks.go +++ b/pkg/testsuite/blocks.go @@ -122,7 +122,7 @@ func (t *TestSuite) AssertBlocksInCacheConflicts(blockConflicts map[*blocks.Bloc return ierrors.Errorf("AssertBlocksInCacheConflicts: %s: block %s is root block", node.Name, blockFromCache.ID()) } - expectedConflictIDs := ds.NewSet(lo.Map(conflictAliases, t.TransactionFramework.TransactionID)...) + expectedConflictIDs := ds.NewSet(lo.Map(conflictAliases, t.TransactionFramework.SignedTransactionID)...) actualConflictIDs := blockFromCache.ConflictIDs() if expectedConflictIDs.Size() != actualConflictIDs.Size() { diff --git a/pkg/testsuite/conflicts.go b/pkg/testsuite/conflicts.go index 7c7047da0..5e8ffd328 100644 --- a/pkg/testsuite/conflicts.go +++ b/pkg/testsuite/conflicts.go @@ -13,7 +13,7 @@ func (t *TestSuite) AssertConflictsInCacheAcceptanceState(expectedConflictAliase for _, node := range nodes { for _, conflictAlias := range expectedConflictAliases { t.Eventually(func() error { - acceptanceState := node.Protocol.MainEngineInstance().Ledger.ConflictDAG().AcceptanceState(ds.NewSet(t.TransactionFramework.TransactionID(conflictAlias))) + acceptanceState := node.Protocol.MainEngineInstance().Ledger.ConflictDAG().AcceptanceState(ds.NewSet(t.TransactionFramework.SignedTransactionID(conflictAlias))) if acceptanceState != expectedState { return ierrors.Errorf("assertTransactionsInCacheWithFunc: %s: conflict %s is %s, but expected %s", node.Name, conflictAlias, acceptanceState, expectedState) diff --git a/pkg/testsuite/mock/hdwallet.go b/pkg/testsuite/mock/hdwallet.go index 9f033627d..a4f6eb4c2 100644 --- a/pkg/testsuite/mock/hdwallet.go +++ b/pkg/testsuite/mock/hdwallet.go @@ -8,6 +8,7 @@ import ( "github.com/wollac/iota-crypto-demo/pkg/slip10" "github.com/wollac/iota-crypto-demo/pkg/slip10/eddsa" + "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota-core/pkg/protocol/engine/utxoledger" iotago "github.com/iotaledger/iota.go/v4" ) @@ -101,11 +102,22 @@ func (hd *HDWallet) Outputs() []*utxoledger.Output { } // Address calculates an ed25519 address by using slip10. -func (hd *HDWallet) Address() *iotago.Ed25519Address { +func (hd *HDWallet) Address(addressType ...iotago.AddressType) iotago.DirectUnlockableAddress { _, pubKey := hd.KeyPair() - addr := iotago.Ed25519AddressFromPubKey(pubKey) - return addr + addrType := iotago.AddressEd25519 + if len(addressType) > 0 { + addrType = addressType[0] + } + + switch addrType { + case iotago.AddressEd25519: + return iotago.Ed25519AddressFromPubKey(pubKey) + case iotago.AddressImplicitAccountCreation: + return iotago.ImplicitAccountCreationAddressFromPubKey(pubKey) + default: + panic(ierrors.Wrapf(iotago.ErrUnknownAddrType, "type %d", addressType)) + } } func (hd *HDWallet) PrintStatus() { diff --git a/pkg/testsuite/testsuite.go b/pkg/testsuite/testsuite.go index 2a13276bc..c9a29042c 100644 --- a/pkg/testsuite/testsuite.go +++ b/pkg/testsuite/testsuite.go @@ -44,24 +44,25 @@ type TestSuite struct { API iotago.API - optsGenesisTimestampOffset int64 - optsLivenessThreshold iotago.SlotIndex - optsMinCommittableAge iotago.SlotIndex - optsMaxCommittableAge iotago.SlotIndex - optsSlotsPerEpochExponent uint8 - optsEpochNearingThreshold iotago.SlotIndex - optsRMCMin iotago.Mana - optsRMCIncrease iotago.Mana - optsRMCDecrease iotago.Mana - optsRMCIncreaseThreshold iotago.WorkScore - optsRMCDecreaseThreshold iotago.WorkScore - optsSchedulerRate iotago.WorkScore - optsMinMana iotago.Mana - optsMaxBufferSize uint32 - optsAccounts []snapshotcreator.AccountDetails - optsSnapshotOptions []options.Option[snapshotcreator.Options] - optsWaitFor time.Duration - optsTick time.Duration + optsGenesisTimestampOffset int64 + optsLivenessThresholdLowerBound uint16 + optsLivenessThresholdUpperBound uint16 + optsMinCommittableAge iotago.SlotIndex + optsMaxCommittableAge iotago.SlotIndex + optsSlotsPerEpochExponent uint8 + optsEpochNearingThreshold iotago.SlotIndex + optsRMCMin iotago.Mana + optsRMCIncrease iotago.Mana + optsRMCDecrease iotago.Mana + optsRMCIncreaseThreshold iotago.WorkScore + optsRMCDecreaseThreshold iotago.WorkScore + optsSchedulerRate iotago.WorkScore + optsMinMana iotago.Mana + optsMaxBufferSize uint32 + optsAccounts []snapshotcreator.AccountDetails + optsSnapshotOptions []options.Option[snapshotcreator.Options] + optsWaitFor time.Duration + optsTick time.Duration uniqueBlockTimeCounter atomic.Int64 automaticTransactionIssuingCounters shrinkingmap.ShrinkingMap[string, int] @@ -82,22 +83,23 @@ func NewTestSuite(testingT *testing.T, opts ...options.Option[TestSuite]) *TestS blocks: shrinkingmap.New[string, *blocks.Block](), automaticTransactionIssuingCounters: *shrinkingmap.New[string, int](), - optsWaitFor: DurationFromEnvOrDefault(5*time.Second, "CI_UNIT_TESTS_WAIT_FOR"), - optsTick: DurationFromEnvOrDefault(2*time.Millisecond, "CI_UNIT_TESTS_TICK"), - optsGenesisTimestampOffset: 0, - optsLivenessThreshold: 3, - optsMinCommittableAge: 10, - optsMaxCommittableAge: 20, - optsSlotsPerEpochExponent: 5, - optsEpochNearingThreshold: 16, - optsRMCMin: 500, - optsRMCIncrease: 500, - optsRMCDecrease: 500, - optsRMCIncreaseThreshold: 8 * schedulerRate, - optsRMCDecreaseThreshold: 5 * schedulerRate, - optsSchedulerRate: schedulerRate, - optsMinMana: 1, - optsMaxBufferSize: 100 * iotago.MaxBlockSize, + optsWaitFor: DurationFromEnvOrDefault(5*time.Second, "CI_UNIT_TESTS_WAIT_FOR"), + optsTick: DurationFromEnvOrDefault(2*time.Millisecond, "CI_UNIT_TESTS_TICK"), + optsGenesisTimestampOffset: 0, + optsLivenessThresholdLowerBound: 30, + optsLivenessThresholdUpperBound: 30, + optsMinCommittableAge: 10, + optsMaxCommittableAge: 20, + optsSlotsPerEpochExponent: 5, + optsEpochNearingThreshold: 16, + optsRMCMin: 500, + optsRMCIncrease: 500, + optsRMCDecrease: 500, + optsRMCIncreaseThreshold: 8 * schedulerRate, + optsRMCDecreaseThreshold: 5 * schedulerRate, + optsSchedulerRate: schedulerRate, + optsMinMana: 1, + optsMaxBufferSize: 100 * iotago.MaxBlockSize, }, opts, func(t *TestSuite) { fmt.Println("Setup TestSuite -", testingT.Name(), " @ ", time.Now()) t.API = iotago.V3API( @@ -121,7 +123,8 @@ func NewTestSuite(testingT *testing.T, opts ...options.Option[TestSuite]) *TestS t.optsSlotsPerEpochExponent, ), iotago.WithLivenessOptions( - t.optsLivenessThreshold, + t.optsLivenessThresholdLowerBound, + t.optsLivenessThresholdUpperBound, t.optsMinCommittableAge, t.optsMaxCommittableAge, t.optsEpochNearingThreshold, diff --git a/pkg/testsuite/testsuite_options.go b/pkg/testsuite/testsuite_options.go index 875c7193c..52fc4f43d 100644 --- a/pkg/testsuite/testsuite_options.go +++ b/pkg/testsuite/testsuite_options.go @@ -39,11 +39,15 @@ func WithGenesisTimestampOffset(offset int64) options.Option[TestSuite] { } } -func WithLivenessThreshold(livenessThreshold iotago.SlotIndex) options.Option[TestSuite] { - // TODO: eventually this should not be used and common parameters should be used +func WithLivenessThresholdLowerBound(lowerBoundInSeconds uint16) options.Option[TestSuite] { + return func(opts *TestSuite) { + opts.optsLivenessThresholdLowerBound = lowerBoundInSeconds + } +} +func WithLivenessThresholdUpperBound(upperBoundInSeconds uint16) options.Option[TestSuite] { return func(opts *TestSuite) { - opts.optsLivenessThreshold = livenessThreshold + opts.optsLivenessThresholdUpperBound = upperBoundInSeconds } } diff --git a/pkg/testsuite/transactions.go b/pkg/testsuite/transactions.go index 33dae4e3d..08fe93fb5 100644 --- a/pkg/testsuite/transactions.go +++ b/pkg/testsuite/transactions.go @@ -12,34 +12,34 @@ import ( iotago "github.com/iotaledger/iota.go/v4" ) -func (t *TestSuite) AssertTransaction(transaction *iotago.Transaction, node *mock.Node) mempool.Transaction { - var loadedTransaction mempool.TransactionMetadata - transactionID, err := transaction.ID() +func (t *TestSuite) AssertTransaction(signedTransaction *iotago.SignedTransaction, node *mock.Node) mempool.Transaction { + var loadedTransactionMetadata mempool.TransactionMetadata + signedTransactionID, err := signedTransaction.ID() require.NoError(t.Testing, err) t.Eventually(func() error { var exists bool - loadedTransaction, exists = node.Protocol.MainEngineInstance().Ledger.TransactionMetadata(transactionID) + loadedTransactionMetadata, exists = node.Protocol.MainEngineInstance().Ledger.TransactionMetadata(signedTransactionID) if !exists { - return ierrors.Errorf("AssertTransaction: %s: transaction %s does not exist", node.Name, transactionID) + return ierrors.Errorf("AssertTransaction: %s: signedTransaction %s does not exist", node.Name, signedTransactionID) } - if transactionID != loadedTransaction.ID() { - return ierrors.Errorf("AssertTransaction: %s: expected ID %s, got %s", node.Name, transactionID, loadedTransaction.ID()) + if signedTransactionID != loadedTransactionMetadata.ID() { + return ierrors.Errorf("AssertTransaction: %s: expected ID %s, got %s", node.Name, signedTransactionID, loadedTransactionMetadata.ID()) } //nolint: forcetypeassert // we are in a test and want to assert it anyway - if !cmp.Equal(transaction.Essence, loadedTransaction.Transaction().(*iotago.Transaction).Essence) { - return ierrors.Errorf("AssertTransaction: %s: expected %s, got %s", node.Name, transaction, loadedTransaction.Transaction()) + if !cmp.Equal(signedTransaction.Transaction, loadedTransactionMetadata.Transaction().(*iotago.SignedTransaction).Transaction) { + return ierrors.Errorf("AssertTransaction: %s: expected %s, got %s", node.Name, signedTransaction, loadedTransactionMetadata.Transaction()) } return nil }) - return loadedTransaction.Transaction() + return loadedTransactionMetadata.Transaction() } -func (t *TestSuite) AssertTransactionsExist(transactions []*iotago.Transaction, expectedExist bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsExist(transactions []*iotago.SignedTransaction, expectedExist bool, nodes ...*mock.Node) { mustNodes(nodes) for _, node := range nodes { @@ -66,7 +66,7 @@ func (t *TestSuite) AssertTransactionsExist(transactions []*iotago.Transaction, } } -func (t *TestSuite) assertTransactionsInCacheWithFunc(expectedTransactions []*iotago.Transaction, expectedPropertyState bool, propertyFunc func(mempool.TransactionMetadata) bool, nodes ...*mock.Node) { +func (t *TestSuite) assertTransactionsInCacheWithFunc(expectedTransactions []*iotago.SignedTransaction, expectedPropertyState bool, propertyFunc func(mempool.TransactionMetadata) bool, nodes ...*mock.Node) { mustNodes(nodes) for _, node := range nodes { @@ -92,31 +92,31 @@ func (t *TestSuite) assertTransactionsInCacheWithFunc(expectedTransactions []*io } } -func (t *TestSuite) AssertTransactionsInCacheAccepted(expectedTransactions []*iotago.Transaction, expectedFlag bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsInCacheAccepted(expectedTransactions []*iotago.SignedTransaction, expectedFlag bool, nodes ...*mock.Node) { t.assertTransactionsInCacheWithFunc(expectedTransactions, expectedFlag, mempool.TransactionMetadata.IsAccepted, nodes...) } -func (t *TestSuite) AssertTransactionsInCacheRejected(expectedTransactions []*iotago.Transaction, expectedFlag bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsInCacheRejected(expectedTransactions []*iotago.SignedTransaction, expectedFlag bool, nodes ...*mock.Node) { t.assertTransactionsInCacheWithFunc(expectedTransactions, expectedFlag, mempool.TransactionMetadata.IsRejected, nodes...) } -func (t *TestSuite) AssertTransactionsInCacheBooked(expectedTransactions []*iotago.Transaction, expectedFlag bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsInCacheBooked(expectedTransactions []*iotago.SignedTransaction, expectedFlag bool, nodes ...*mock.Node) { t.assertTransactionsInCacheWithFunc(expectedTransactions, expectedFlag, mempool.TransactionMetadata.IsBooked, nodes...) } -func (t *TestSuite) AssertTransactionsInCacheConflicting(expectedTransactions []*iotago.Transaction, expectedFlag bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsInCacheConflicting(expectedTransactions []*iotago.SignedTransaction, expectedFlag bool, nodes ...*mock.Node) { t.assertTransactionsInCacheWithFunc(expectedTransactions, expectedFlag, mempool.TransactionMetadata.IsConflicting, nodes...) } -func (t *TestSuite) AssertTransactionsInCacheInvalid(expectedTransactions []*iotago.Transaction, expectedFlag bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsInCacheInvalid(expectedTransactions []*iotago.SignedTransaction, expectedFlag bool, nodes ...*mock.Node) { t.assertTransactionsInCacheWithFunc(expectedTransactions, expectedFlag, mempool.TransactionMetadata.IsInvalid, nodes...) } -func (t *TestSuite) AssertTransactionsInCachePending(expectedTransactions []*iotago.Transaction, expectedFlag bool, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionsInCachePending(expectedTransactions []*iotago.SignedTransaction, expectedFlag bool, nodes ...*mock.Node) { t.assertTransactionsInCacheWithFunc(expectedTransactions, expectedFlag, mempool.TransactionMetadata.IsPending, nodes...) } -func (t *TestSuite) AssertTransactionInCacheConflicts(transactionConflicts map[*iotago.Transaction][]string, nodes ...*mock.Node) { +func (t *TestSuite) AssertTransactionInCacheConflicts(transactionConflicts map[*iotago.SignedTransaction][]string, nodes ...*mock.Node) { for _, node := range nodes { for transaction, conflictAliases := range transactionConflicts { transactionID, err := transaction.ID() @@ -128,7 +128,7 @@ func (t *TestSuite) AssertTransactionInCacheConflicts(transactionConflicts map[* return ierrors.Errorf("AssertTransactionInCacheConflicts: %s: block %s does not exist", node.Name, transactionID) } - expectedConflictIDs := ds.NewSet(lo.Map(conflictAliases, t.TransactionFramework.TransactionID)...) + expectedConflictIDs := ds.NewSet(lo.Map(conflictAliases, t.TransactionFramework.SignedTransactionID)...) actualConflictIDs := transactionFromCache.ConflictIDs() if expectedConflictIDs.Size() != actualConflictIDs.Size() { diff --git a/pkg/testsuite/transactions_framework.go b/pkg/testsuite/transactions_framework.go index aaffe1e68..e2bc2dcfe 100644 --- a/pkg/testsuite/transactions_framework.go +++ b/pkg/testsuite/transactions_framework.go @@ -21,7 +21,7 @@ type TransactionFramework struct { wallet *mock.HDWallet states map[string]*utxoledger.Output - transactions map[string]*iotago.Transaction + transactions map[string]*iotago.SignedTransaction } func NewTransactionFramework(protocol *protocol.Protocol, genesisSeed []byte, accounts ...snapshotcreator.AccountDetails) *TransactionFramework { @@ -34,7 +34,7 @@ func NewTransactionFramework(protocol *protocol.Protocol, genesisSeed []byte, ac tf := &TransactionFramework{ apiProvider: protocol, states: map[string]*utxoledger.Output{"Genesis:0": genesisOutput}, - transactions: make(map[string]*iotago.Transaction), + transactions: make(map[string]*iotago.SignedTransaction), wallet: mock.NewHDWallet("genesis", genesisSeed, 0), } @@ -50,7 +50,7 @@ func NewTransactionFramework(protocol *protocol.Protocol, genesisSeed []byte, ac return tf } -func (t *TransactionFramework) RegisterTransaction(alias string, transaction *iotago.Transaction) { +func (t *TransactionFramework) RegisterTransaction(alias string, transaction *iotago.SignedTransaction) { currentAPI := t.apiProvider.CurrentAPI() (lo.PanicOnErr(transaction.ID())).RegisterAlias(alias) @@ -69,13 +69,17 @@ func (t *TransactionFramework) RegisterTransaction(alias string, transaction *io } } -func (t *TransactionFramework) CreateTransactionWithOptions(alias string, signingWallets []*mock.HDWallet, opts ...options.Option[builder.TransactionBuilder]) (*iotago.Transaction, error) { +func (t *TransactionFramework) CreateTransactionWithOptions(alias string, signingWallets []*mock.HDWallet, opts ...options.Option[builder.TransactionBuilder]) (*iotago.SignedTransaction, error) { currentAPI := t.apiProvider.CurrentAPI() - walletKeys := make([]iotago.AddressKeys, len(signingWallets)) - for i, wallet := range signingWallets { + walletKeys := make([]iotago.AddressKeys, 0, len(signingWallets)*2) + for _, wallet := range signingWallets { inputPrivateKey, _ := wallet.KeyPair() - walletKeys[i] = iotago.AddressKeys{Address: wallet.Address(), Keys: inputPrivateKey} + // add address keys for both types of directly unlockable addresses to simplify the TransactionFramework + //nolint:forcetypeassert + walletKeys = append(walletKeys, iotago.NewAddressKeysForEd25519Address(wallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address), inputPrivateKey)) + //nolint:forcetypeassert + walletKeys = append(walletKeys, iotago.NewAddressKeysForImplicitAccountCreationAddress(wallet.Address(iotago.AddressImplicitAccountCreation).(*iotago.ImplicitAccountCreationAddress), inputPrivateKey)) } txBuilder := builder.NewTransactionBuilder(currentAPI) @@ -92,7 +96,7 @@ func (t *TransactionFramework) CreateTransactionWithOptions(alias string, signin return tx, err } -func (t *TransactionFramework) CreateSimpleTransaction(alias string, outputCount int, inputAliases ...string) (*iotago.Transaction, error) { +func (t *TransactionFramework) CreateSimpleTransaction(alias string, outputCount int, inputAliases ...string) (*iotago.SignedTransaction, error) { inputStates, outputStates, signingWallets := t.CreateBasicOutputsEqually(outputCount, inputAliases...) return t.CreateTransactionWithOptions(alias, signingWallets, WithInputs(inputStates), WithOutputs(outputStates)) @@ -175,20 +179,14 @@ func (t *TransactionFramework) CreateBasicOutputs(amountDistribution []iotago.Ba return inputStates, outputStates, []*mock.HDWallet{t.wallet} } -func (t *TransactionFramework) CreateAccountFromInput(inputAlias string, opts ...options.Option[iotago.AccountOutput]) (utxoledger.Outputs, iotago.Outputs[iotago.Output], []*mock.HDWallet) { +func (t *TransactionFramework) CreateAccountFromInput(inputAlias string, opts ...options.Option[builder.AccountOutputBuilder]) (utxoledger.Outputs, iotago.Outputs[iotago.Output], []*mock.HDWallet) { input := t.Output(inputAlias) - accountOutput := options.Apply(&iotago.AccountOutput{ - Amount: input.BaseTokenAmount(), - Mana: input.StoredMana(), - NativeTokens: iotago.NativeTokens{}, - Conditions: iotago.AccountOutputUnlockConditions{ - &iotago.StateControllerAddressUnlockCondition{Address: t.DefaultAddress()}, - &iotago.GovernorAddressUnlockCondition{Address: t.DefaultAddress()}, - }, - Features: iotago.AccountOutputFeatures{}, - ImmutableFeatures: iotago.AccountOutputImmFeatures{}, - }, opts) + accountOutput := options.Apply(builder.NewAccountOutputBuilder(t.DefaultAddress(), t.DefaultAddress(), input.BaseTokenAmount()). + Mana(input.StoredMana()). + StateController(t.DefaultAddress()). + Governor(t.DefaultAddress()), + opts).MustBuild() outputStates := iotago.Outputs[iotago.Output]{accountOutput} @@ -208,23 +206,35 @@ func (t *TransactionFramework) CreateAccountFromInput(inputAlias string, opts .. return utxoledger.Outputs{input}, outputStates, []*mock.HDWallet{t.wallet} } +// CreateImplicitAccountFromInput creates an implicit account output. +func (t *TransactionFramework) CreateImplicitAccountFromInput(inputAlias string) (utxoledger.Outputs, iotago.Outputs[iotago.Output], *iotago.ImplicitAccountCreationAddress, []*mock.HDWallet) { + input := t.Output(inputAlias) + + //nolint:forcetypeassert + implicitAccountAddress := t.DefaultAddress(iotago.AddressImplicitAccountCreation).(*iotago.ImplicitAccountCreationAddress) + + basicOutput := &iotago.BasicOutput{ + Amount: input.BaseTokenAmount(), + Mana: input.StoredMana(), + NativeTokens: iotago.NativeTokens{}, + Conditions: iotago.BasicOutputUnlockConditions{ + &iotago.AddressUnlockCondition{Address: implicitAccountAddress}, + }, + Features: iotago.BasicOutputFeatures{}, + } + + return utxoledger.Outputs{input}, iotago.Outputs[iotago.Output]{basicOutput}, implicitAccountAddress, []*mock.HDWallet{t.wallet} +} + // CreateDelegationFromInput creates a new DelegationOutput with given options from an input. If the remainder Output // is not created, then StoredMana from the input is not passed and can potentially be burned. // In order not to burn it, it needs to be assigned manually in another output in the transaction. -func (t *TransactionFramework) CreateDelegationFromInput(inputAlias string, opts ...options.Option[iotago.DelegationOutput]) (utxoledger.Outputs, iotago.Outputs[iotago.Output], []*mock.HDWallet) { +func (t *TransactionFramework) CreateDelegationFromInput(inputAlias string, opts ...options.Option[builder.DelegationOutputBuilder]) (utxoledger.Outputs, iotago.Outputs[iotago.Output], []*mock.HDWallet) { input := t.Output(inputAlias) - delegationOutput := options.Apply(&iotago.DelegationOutput{ - Amount: input.BaseTokenAmount(), - DelegatedAmount: input.BaseTokenAmount(), - DelegationID: iotago.DelegationID{}, - ValidatorAddress: &iotago.AccountAddress{}, - StartEpoch: 0, - EndEpoch: 0, - Conditions: iotago.DelegationOutputUnlockConditions{ - &iotago.AddressUnlockCondition{Address: t.DefaultAddress()}, - }, - }, opts) + delegationOutput := options.Apply(builder.NewDelegationOutputBuilder(&iotago.AccountAddress{}, t.DefaultAddress(), input.BaseTokenAmount()). + DelegatedAmount(input.BaseTokenAmount()), + opts).MustBuild() if delegationOutput.ValidatorAddress.AccountID() == iotago.EmptyAccountID() || delegationOutput.DelegatedAmount == 0 || @@ -257,17 +267,17 @@ func (t *TransactionFramework) DelayedClaimingTransition(inputAlias string, dele panic(ierrors.Errorf("%s is not a delegation output, cannot transition to delayed claiming state", inputAlias)) } - delegationOutput, ok := input.Output().Clone().(*iotago.DelegationOutput) + prevOutput, ok := input.Output().Clone().(*iotago.DelegationOutput) if !ok { panic(ierrors.Errorf("cloned output %s is not a delegation output, cannot transition to delayed claiming state", inputAlias)) } - if delegationOutput.DelegationID == iotago.EmptyDelegationID() { - delegationOutput.DelegationID = iotago.DelegationIDFromOutputID(input.OutputID()) + delegationBuilder := builder.NewDelegationOutputBuilderFromPrevious(prevOutput).EndEpoch(delegationEndEpoch) + if prevOutput.DelegationID == iotago.EmptyDelegationID() { + delegationBuilder.DelegationID(iotago.DelegationIDFromOutputID(input.OutputID())) } - delegationOutput.EndEpoch = delegationEndEpoch - return utxoledger.Outputs{input}, iotago.Outputs[iotago.Output]{delegationOutput}, []*mock.HDWallet{t.wallet} + return utxoledger.Outputs{input}, iotago.Outputs[iotago.Output]{delegationBuilder.MustBuild()}, []*mock.HDWallet{t.wallet} } func (t *TransactionFramework) DestroyAccount(alias string) (consumedInputs *utxoledger.Output, outputs iotago.Outputs[iotago.Output], signingWallets []*mock.HDWallet) { @@ -286,7 +296,7 @@ func (t *TransactionFramework) DestroyAccount(alias string) (consumedInputs *utx return output, outputStates, []*mock.HDWallet{t.wallet} } -func (t *TransactionFramework) TransitionAccount(alias string, opts ...options.Option[iotago.AccountOutput]) (consumedInput *utxoledger.Output, outputs iotago.Outputs[iotago.Output], signingWallets []*mock.HDWallet) { +func (t *TransactionFramework) TransitionAccount(alias string, opts ...options.Option[builder.AccountOutputBuilder]) (consumedInput *utxoledger.Output, outputs iotago.Outputs[iotago.Output], signingWallets []*mock.HDWallet) { output, exists := t.states[alias] if !exists { panic(fmt.Sprintf("account with alias %s does not exist", alias)) @@ -297,11 +307,34 @@ func (t *TransactionFramework) TransitionAccount(alias string, opts ...options.O panic(fmt.Sprintf("output with alias %s is not *iotago.AccountOutput", alias)) } - accountOutput = options.Apply(accountOutput, opts) + accountBuilder := builder.NewAccountOutputBuilderFromPrevious(accountOutput) + accountOutput = options.Apply(accountBuilder, opts).MustBuild() return output, iotago.Outputs[iotago.Output]{accountOutput}, []*mock.HDWallet{t.wallet} } +func (t *TransactionFramework) TransitionImplicitAccountToAccountOutput(alias string, opts ...options.Option[builder.AccountOutputBuilder]) (consumedInput utxoledger.Outputs, outputs iotago.Outputs[iotago.Output], signingWallets []*mock.HDWallet) { + input, exists := t.states[alias] + if !exists { + panic(fmt.Sprintf("output with alias %s does not exist", alias)) + } + + basicOutput, isBasic := input.Output().(*iotago.BasicOutput) + if !isBasic { + panic(fmt.Sprintf("output with alias %s is not *iotago.BasicOutput", alias)) + } + if basicOutput.UnlockConditionSet().Address().Address.Type() != iotago.AddressImplicitAccountCreation { + panic(fmt.Sprintf("output with alias %s is not an implicit account", alias)) + } + + accountOutput := options.Apply(builder.NewAccountOutputBuilder(t.DefaultAddress(), t.DefaultAddress(), input.BaseTokenAmount()). + Mana(input.StoredMana()). + AccountID(iotago.AccountIDFromOutputID(input.OutputID())), + opts).MustBuild() + + return utxoledger.Outputs{input}, iotago.Outputs[iotago.Output]{accountOutput}, []*mock.HDWallet{t.wallet} +} + func (t *TransactionFramework) Output(alias string) *utxoledger.Output { output, exists := t.states[alias] if !exists { @@ -315,7 +348,7 @@ func (t *TransactionFramework) OutputID(alias string) iotago.OutputID { return t.Output(alias).OutputID() } -func (t *TransactionFramework) Transaction(alias string) *iotago.Transaction { +func (t *TransactionFramework) SignedTransaction(alias string) *iotago.SignedTransaction { transaction, exists := t.transactions[alias] if !exists { panic(ierrors.Errorf("transaction with given alias does not exist %s", alias)) @@ -324,181 +357,152 @@ func (t *TransactionFramework) Transaction(alias string) *iotago.Transaction { return transaction } -func (t *TransactionFramework) TransactionID(alias string) iotago.TransactionID { - return lo.PanicOnErr(t.Transaction(alias).ID()) +func (t *TransactionFramework) SignedTransactionID(alias string) iotago.SignedTransactionID { + return lo.PanicOnErr(t.SignedTransaction(alias).ID()) } -func (t *TransactionFramework) Transactions(aliases ...string) []*iotago.Transaction { - return lo.Map(aliases, t.Transaction) +func (t *TransactionFramework) SignedTransactions(aliases ...string) []*iotago.SignedTransaction { + return lo.Map(aliases, t.SignedTransaction) } -func (t *TransactionFramework) TransactionIDs(aliases ...string) []iotago.TransactionID { - return lo.Map(aliases, t.TransactionID) +func (t *TransactionFramework) SignedTransactionIDs(aliases ...string) []iotago.SignedTransactionID { + return lo.Map(aliases, t.SignedTransactionID) } -func (t *TransactionFramework) DefaultAddress() iotago.Address { - return t.wallet.Address() +func (t *TransactionFramework) DefaultAddress(addressType ...iotago.AddressType) iotago.Address { + return t.wallet.Address(addressType...) } // DelegationOutput options -func WithDelegatedAmount(delegatedAmount iotago.BaseToken) options.Option[iotago.DelegationOutput] { - return func(delegationOutput *iotago.DelegationOutput) { - delegationOutput.DelegatedAmount = delegatedAmount +func WithDelegatedAmount(delegatedAmount iotago.BaseToken) options.Option[builder.DelegationOutputBuilder] { + return func(delegationBuilder *builder.DelegationOutputBuilder) { + delegationBuilder.DelegatedAmount(delegatedAmount) } } -func WithDelegatedValidatorAddress(validatorAddress *iotago.AccountAddress) options.Option[iotago.DelegationOutput] { - return func(delegationOutput *iotago.DelegationOutput) { - delegationOutput.ValidatorAddress = validatorAddress +func WithDelegatedValidatorAddress(validatorAddress *iotago.AccountAddress) options.Option[builder.DelegationOutputBuilder] { + return func(delegationBuilder *builder.DelegationOutputBuilder) { + delegationBuilder.ValidatorAddress(validatorAddress) } } -func WithDelegationStartEpoch(startEpoch iotago.EpochIndex) options.Option[iotago.DelegationOutput] { - return func(delegationOutput *iotago.DelegationOutput) { - delegationOutput.StartEpoch = startEpoch +func WithDelegationStartEpoch(startEpoch iotago.EpochIndex) options.Option[builder.DelegationOutputBuilder] { + return func(delegationBuilder *builder.DelegationOutputBuilder) { + delegationBuilder.StartEpoch(startEpoch) } } -func WithDelegationEndEpoch(endEpoch iotago.EpochIndex) options.Option[iotago.DelegationOutput] { - return func(delegationOutput *iotago.DelegationOutput) { - delegationOutput.EndEpoch = endEpoch +func WithDelegationEndEpoch(endEpoch iotago.EpochIndex) options.Option[builder.DelegationOutputBuilder] { + return func(delegationBuilder *builder.DelegationOutputBuilder) { + delegationBuilder.EndEpoch(endEpoch) } } -func WithDelegationConditions(delegationConditions iotago.DelegationOutputUnlockConditions) options.Option[iotago.DelegationOutput] { - return func(delegationOutput *iotago.DelegationOutput) { - delegationOutput.Conditions = delegationConditions +func WithDelegationConditions(delegationConditions iotago.DelegationOutputUnlockConditions) options.Option[builder.DelegationOutputBuilder] { + return func(delegationBuilder *builder.DelegationOutputBuilder) { + delegationBuilder.Address(delegationConditions.MustSet().Address().Address) } } -func WithDelegationAmount(amount iotago.BaseToken) options.Option[iotago.DelegationOutput] { - return func(delegationOutput *iotago.DelegationOutput) { - delegationOutput.Amount = amount +func WithDelegationAmount(amount iotago.BaseToken) options.Option[builder.DelegationOutputBuilder] { + return func(delegationBuilder *builder.DelegationOutputBuilder) { + delegationBuilder.Amount(amount) } } // BlockIssuer options -func WithBlockIssuerFeature(blockIssuerFeature *iotago.BlockIssuerFeature) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - for idx, feature := range accountOutput.Features { - if feature.Type() == iotago.FeatureBlockIssuer { - accountOutput.Features[idx] = blockIssuerFeature - return - } - } - - accountOutput.Features = append(accountOutput.Features, blockIssuerFeature) +func WithBlockIssuerFeature(keys iotago.BlockIssuerKeys, expirySlot iotago.SlotIndex) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + accountBuilder.BlockIssuer(keys, expirySlot) } } -func AddBlockIssuerKey(key iotago.BlockIssuerKey) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - blockIssuer := accountOutput.FeatureSet().BlockIssuer() - if blockIssuer == nil { - panic("cannot add block issuer key to account without BlockIssuer feature") - } - blockIssuer.BlockIssuerKeys = append(blockIssuer.BlockIssuerKeys, key) - - blockIssuer.BlockIssuerKeys.Sort() +func WithAddBlockIssuerKey(key iotago.BlockIssuerKey) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + transition := accountBuilder.GovernanceTransition() + transition.BlockIssuerTransition().AddKeys(key) } } -func WithBlockIssuerKeys(keys iotago.BlockIssuerKeys) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - blockIssuer := accountOutput.FeatureSet().BlockIssuer() - if blockIssuer == nil { - panic("cannot set block issuer keys to account without BlockIssuer feature") - } - blockIssuer.BlockIssuerKeys = keys - } -} - -func WithBlockIssuerExpirySlot(expirySlot iotago.SlotIndex) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - blockIssuer := accountOutput.FeatureSet().BlockIssuer() - if blockIssuer == nil { - panic("cannot set block issuer expiry slot to account without BlockIssuer feature") - } - blockIssuer.ExpirySlot = expirySlot +func WithBlockIssuerKeys(keys iotago.BlockIssuerKeys) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + transition := accountBuilder.GovernanceTransition() + transition.BlockIssuerTransition().Keys(keys) } } -func WithStakingFeature(stakingFeature *iotago.StakingFeature) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - for idx, feature := range accountOutput.Features { - if feature.Type() == iotago.FeatureStaking { - accountOutput.Features[idx] = stakingFeature - return - } - } - - accountOutput.Features = append(accountOutput.Features, stakingFeature) +func WithBlockIssuerExpirySlot(expirySlot iotago.SlotIndex) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + transition := accountBuilder.GovernanceTransition() + transition.BlockIssuerTransition().ExpirySlot(expirySlot) } } -func WithStakingEndEpoch(endEpoch iotago.EpochIndex) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - staking := accountOutput.FeatureSet().Staking() - if staking == nil { - panic("cannot update staking end epoch on account without Staking feature") - } - staking.EndEpoch = endEpoch +func WithStakingFeature(amount iotago.BaseToken, fixedCost iotago.Mana, startEpoch iotago.EpochIndex, optEndEpoch ...iotago.EpochIndex) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + accountBuilder.Staking(amount, fixedCost, startEpoch, optEndEpoch...) } } // Account options -func WithAccountMana(mana iotago.Mana) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.Mana = mana +func WithAccountMana(mana iotago.Mana) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + accountBuilder.Mana(mana) } } -func WithAccountAmount(amount iotago.BaseToken) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.Amount = amount +func WithAccountAmount(amount iotago.BaseToken) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + accountBuilder.Amount(amount) } } -func WithAccountIncreasedStateIndex() options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.StateIndex++ +func WithAccountIncreasedFoundryCounter(diff uint32) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + accountBuilder.FoundriesToGenerate(diff) } } -func WithAccountIncreasedFoundryCounter(diff uint32) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.FoundryCounter += diff - } -} - -func WithAccountFeatures(features iotago.AccountOutputFeatures) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.Features = features - } -} - -func WithAccountImmutableFeatures(features iotago.AccountOutputImmFeatures) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.ImmutableFeatures = features +func WithAccountImmutableFeatures(features iotago.AccountOutputImmFeatures) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + for _, feature := range features.MustSet() { + switch feature.Type() { + case iotago.FeatureMetadata: + //nolint:forcetypeassert + accountBuilder.ImmutableMetadata(feature.(*iotago.MetadataFeature).Data) + case iotago.FeatureSender: + //nolint:forcetypeassert + accountBuilder.ImmutableSender(feature.(*iotago.SenderFeature).Address) + } + } } } -func WithAccountConditions(conditions iotago.AccountOutputUnlockConditions) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.Conditions = conditions +func WithAccountConditions(conditions iotago.AccountOutputUnlockConditions) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + for _, condition := range conditions.MustSet() { + switch condition.Type() { + case iotago.UnlockConditionStateControllerAddress: + //nolint:forcetypeassert + accountBuilder.StateController(condition.(*iotago.StateControllerAddressUnlockCondition).Address) + case iotago.UnlockConditionGovernorAddress: + //nolint:forcetypeassert + accountBuilder.Governor(condition.(*iotago.GovernorAddressUnlockCondition).Address) + } + } } } -func WithAccountNativeTokens(nativeTokens iotago.NativeTokens) options.Option[iotago.AccountOutput] { - return func(accountOutput *iotago.AccountOutput) { - accountOutput.NativeTokens = nativeTokens +func WithAccountNativeTokens(nativeTokens iotago.NativeTokens) options.Option[builder.AccountOutputBuilder] { + return func(accountBuilder *builder.AccountOutputBuilder) { + accountBuilder.NativeTokens(nativeTokens) } } -// Transaction options +// TransactionBuilder options func WithInputs(inputs utxoledger.Outputs) options.Option[builder.TransactionBuilder] { return func(txBuilder *builder.TransactionBuilder) { @@ -551,7 +555,7 @@ func WithAccountInput(input *utxoledger.Output, governorTransition bool) options func WithAllotments(allotments iotago.Allotments) options.Option[builder.TransactionBuilder] { return func(txBuilder *builder.TransactionBuilder) { for _, allotment := range allotments { - txBuilder.AddAllotment(allotment) + txBuilder.IncreaseAllotment(allotment.AccountID, allotment.Value) } } } diff --git a/tools/evil-spammer/go.mod b/tools/evil-spammer/go.mod index 24712bfb5..1bf9c21c4 100644 --- a/tools/evil-spammer/go.mod +++ b/tools/evil-spammer/go.mod @@ -8,16 +8,16 @@ 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-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 + github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 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-20230927112835-2dc846c6153f + github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c github.com/mr-tron/base58 v1.2.0 go.uber.org/atomic v1.11.0 ) @@ -37,13 +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-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 // indirect + github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 // 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 8c6d6720e..6b2afa47f 100644 --- a/tools/evil-spammer/go.sum +++ b/tools/evil-spammer/go.sum @@ -169,36 +169,34 @@ 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-20230927122328-da2eaee8d805 h1:OtCoTjJlQeICgv+MitK/okK9TldywK7jue8jI8k78eg= -github.com/iotaledger/hive.go/ads v0.0.0-20230927122328-da2eaee8d805/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805 h1:9JZsyrQHMWoaDmcw5ssgQn8YMFix2cOE36ha7DGhY2A= -github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 h1:2vSacMbBgQSAD+sNptWJQrJchIS+j9gEABYSYlUulg0= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 h1:vfY5UFZeybxNTB5NYJAcQxxngSmnWMkemB5C6KKcG+Y= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 h1:teasrvb1DqJqOcVAxH15ZdGIPdNHI+lCU9OOrPBfHVc= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 h1:pj5K1GCyW8ugsL8QXHGkNmWEucoY3yJC/W5uBwxXEvQ= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 h1:heT6TrgjINpwnmUMo7uDJ5vdEpuStDIbDWcCdbTl6+I= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 h1:aFd/nvj8qkO+6qwaaUFwbfD4z9LhHZiDMFKzAzEZaE0= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 h1:aeJ/8Q6qw1fC6Mf3SGLwDwy2ZWVdG4q/9zNbKElVXmU= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 h1:i4DN1/Pbzd/QhbGddRPO8N18ZwrB7yzkFLHjgx1unk8= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805/go.mod h1:UF7PzlWdZ2H0Hkxrt4AgJmNVeMXUJzw4RwbHpib1DB0= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 h1:35L6o/GmpOy8GrcsnNSvBR1/Cqzt60Qt/4DniPCOOZY= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 h1:9UoQ4V2NxrUHT4m+LL1/PmexuZYpelDlaLBEimO5w+k= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 h1:2ls3eCyGrHaHEYMxKsdd6S5pmjAzwUrOG2G5O4dsJp0= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 h1:dXXdK66EE7/2/lgfmwU0J+avEYLryKe0Kpn63Kmn+xo= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f h1:b7mr4pVMRsqp4BMXFA6GR911t/10AmvZIjsvgLJegRQ= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 h1:HHxgNhbtD6WDCwSQBbPrQe8c4ZNjNi0KcgCJo0nm9bY= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729 h1:rBADf+IZDKkDOuZznwIdonxF9jcOSQJU/qOYSNInX84= +github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 h1:PQ9TFyXBrV6LLTOzE43CV/vz+ItN5v6lcA7ms0YOvcE= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 h1:mwIZhduBiOD4rG4hqrPhW616EU1wX4eD2zHu26be5Yc= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 h1:FpFlPNOHcvHDyk1gN3OuL/hgvTKVsc5IN+q8U1YF9P4= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 h1:hHdIZn95+HdP1JdjV8TAsuL5kU4eb4gncehyjXo/feQ= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 h1:+/OtOAx2tMy8ER3XBt9RpnspWyDrVqW6kQGAd24jT0k= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 h1:XCYvP8XwETTXF5LNz8q9X3EajDut7+UwTwqJ2TQ0TJo= +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-20230928074706-d58e32f86729 h1:hW4r9no+03ufp2fyx4IjTFwINkEz3OI3LqvSjv7SJ1c= +github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729 h1:FOQetJY2scpCtCGrZQWGw3RwB3lRIDdyu+M6P1NACM4= +github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 h1:4aRR9UG4dHpdlTcMN1Px++eaxlGXXk1n6co8t/WlchM= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 h1:mPmP3/0XJAf0ZkCzQenpoQPMv+m56Z8+A1i/UO18Hdw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 h1:gZlIK1OzdA3aZ78PsiWe3poVzawyw4S3zboMHE1TrY0= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c h1:faTwv2r4EZ6FixcFtaSD5M02YRm+/kmQKsLBsYSJl3I= +github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= 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/evil-spammer/spammer/spammer.go b/tools/evil-spammer/spammer/spammer.go index 4b870351e..19333aa2d 100644 --- a/tools/evil-spammer/spammer/spammer.go +++ b/tools/evil-spammer/spammer/spammer.go @@ -224,16 +224,16 @@ func (s *Spammer) StopSpamming() { // PostTransaction use provided client to issue a transaction. It chooses API method based on Spammer options. Counts errors, // counts transactions and provides debug logs. -func (s *Spammer) PostTransaction(tx *iotago.Transaction, clt wallet.Client) { - if tx == nil { +func (s *Spammer) PostTransaction(signedTx *iotago.SignedTransaction, clt wallet.Client) { + if signedTx == nil { s.log.Debug(ErrTransactionIsNil) s.ErrCounter.CountError(ErrTransactionIsNil) return } - txID := lo.PanicOnErr(tx.ID()) - allSolid := s.handleSolidityForReuseOutputs(clt, tx) + txID := lo.PanicOnErr(signedTx.ID()) + allSolid := s.handleSolidityForReuseOutputs(clt, signedTx) if !allSolid { s.log.Debug(ErrInputsNotSolid) s.ErrCounter.CountError(ierrors.Wrapf(ErrInputsNotSolid, "txID: %s", txID.ToHex())) @@ -241,7 +241,7 @@ func (s *Spammer) PostTransaction(tx *iotago.Transaction, clt wallet.Client) { return } - blockID, err := clt.PostTransaction(tx) + blockID, err := clt.PostTransaction(signedTx) if err != nil { s.log.Debug(ierrors.Wrapf(ErrFailPostTransaction, err.Error())) s.ErrCounter.CountError(ierrors.Wrapf(ErrFailPostTransaction, err.Error())) @@ -250,7 +250,7 @@ func (s *Spammer) PostTransaction(tx *iotago.Transaction, clt wallet.Client) { } if s.EvilScenario.OutputWallet.Type() == wallet.Reuse { var outputIDs iotago.OutputIDs - for index := range tx.Essence.Outputs { + for index := range signedTx.Transaction.Outputs { outputIDs = append(outputIDs, iotago.OutputIDFromTransactionIDAndIndex(txID, uint16(index))) } s.EvilWallet.SetTxOutputsSolid(outputIDs, clt.URL()) @@ -260,10 +260,10 @@ func (s *Spammer) PostTransaction(tx *iotago.Transaction, clt wallet.Client) { s.log.Debugf("%s: Last transaction sent, ID: %s, txCount: %d", blockID.ToHex(), txID.ToHex(), count) } -func (s *Spammer) handleSolidityForReuseOutputs(_ wallet.Client, _ *iotago.Transaction) (ok bool) { - // ok = s.EvilWallet.AwaitInputsSolidity(tx.Essence().Inputs(), clt) +func (s *Spammer) handleSolidityForReuseOutputs(_ wallet.Client, _ *iotago.SignedTransaction) (ok bool) { + // ok = s.EvilWallet.AwaitInputsSolidity(tx.SignedTransaction().Inputs(), clt) // if s.EvilScenario.OutputWallet.Type() == wallet.Reuse { - // s.EvilWallet.AddReuseOutputsToThePool(tx.Essence().Outputs()) + // s.EvilWallet.AddReuseOutputsToThePool(tx.SignedTransaction().Outputs()) // } return true } diff --git a/tools/evil-spammer/spammer/spamming_functions.go b/tools/evil-spammer/spammer/spamming_functions.go index 1473ce8cb..7eca19a76 100644 --- a/tools/evil-spammer/spammer/spamming_functions.go +++ b/tools/evil-spammer/spammer/spamming_functions.go @@ -50,7 +50,7 @@ func CustomConflictSpammingFunc(s *Spammer) { wg := sync.WaitGroup{} for i, tx := range txs { wg.Add(1) - go func(clt wallet.Client, tx *iotago.Transaction) { + go func(clt wallet.Client, tx *iotago.SignedTransaction) { defer wg.Done() // sleep randomly to avoid issuing blocks in different goroutines at once diff --git a/tools/evil-spammer/wallet/connector.go b/tools/evil-spammer/wallet/connector.go index cf7da96aa..e02c81b00 100644 --- a/tools/evil-spammer/wallet/connector.go +++ b/tools/evil-spammer/wallet/connector.go @@ -162,7 +162,7 @@ type Client interface { // URL returns a client API url. URL() (cltID string) // PostTransaction sends a transaction to the Tangle via a given client. - PostTransaction(tx *iotago.Transaction) (iotago.BlockID, error) + PostTransaction(tx *iotago.SignedTransaction) (iotago.BlockID, error) // PostData sends the given data (payload) by creating a block in the backend. PostData(data []byte) (blkID string, err error) // GetTransactionConfirmationState returns the AcceptanceState of a given transaction ID. @@ -172,7 +172,7 @@ type Client interface { // GetOutputConfirmationState gets the first unspent outputs of a given address. GetOutputConfirmationState(outputID iotago.OutputID) string // GetTransaction gets the transaction. - GetTransaction(txID iotago.TransactionID) (resp *iotago.Transaction, err error) + GetTransaction(txID iotago.TransactionID) (resp *iotago.SignedTransaction, err error) // GetBlockIssuance returns the latest commitment and data needed to create a new block. GetBlockIssuance() (resp *apimodels.IssuanceBlockHeaderResponse, err error) @@ -220,7 +220,7 @@ func NewWebClient(url string, opts ...options.Option[WebClient]) *WebClient { } // PostTransaction sends a transaction to the Tangle via a given client. -func (c *WebClient) PostTransaction(tx *iotago.Transaction) (blockID iotago.BlockID, err error) { +func (c *WebClient) PostTransaction(tx *iotago.SignedTransaction) (blockID iotago.BlockID, err error) { blockBuilder := builder.NewBasicBlockBuilder(c.client.CurrentAPI()) blockBuilder.Payload(tx) @@ -289,7 +289,7 @@ func (c *WebClient) GetTransactionConfirmationState(txID iotago.TransactionID) s } // GetTransaction gets the transaction. -func (c *WebClient) GetTransaction(txID iotago.TransactionID) (tx *iotago.Transaction, err error) { +func (c *WebClient) GetTransaction(txID iotago.TransactionID) (tx *iotago.SignedTransaction, err error) { resp, err := c.client.TransactionIncludedBlock(context.Background(), txID) if err != nil { return @@ -300,7 +300,7 @@ func (c *WebClient) GetTransaction(txID iotago.TransactionID) (tx *iotago.Transa return } - tx, _ = modelBlk.Transaction() + tx, _ = modelBlk.SignedTransaction() return tx, nil } diff --git a/tools/evil-spammer/wallet/evilwallet.go b/tools/evil-spammer/wallet/evilwallet.go index b1f8fe11e..05e41ae6f 100644 --- a/tools/evil-spammer/wallet/evilwallet.go +++ b/tools/evil-spammer/wallet/evilwallet.go @@ -291,27 +291,27 @@ func (e *EvilWallet) requestFaucetFunds(wallet *Wallet) (outputID *Output, err e txBuilder.AddTaggedDataPayload(&iotago.TaggedData{Tag: []byte("faucet funds"), Data: []byte("to addr" + receiveAddr.String())}) txBuilder.SetCreationSlot(clt.CurrentAPI().TimeProvider().SlotFromTime(time.Now())) - tx, err := txBuilder.Build(e.faucet.AddressSigner(faucetAddr)) + signedTx, err := txBuilder.Build(e.faucet.AddressSigner(faucetAddr)) if err != nil { return nil, err } // send transaction - _, err = clt.PostTransaction(tx) + _, err = clt.PostTransaction(signedTx) if err != nil { return nil, err } // requested output to split and use in spammer - output := e.outputManager.CreateOutputFromAddress(wallet, receiveAddr, faucetTokensPerRequest, iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(tx.ID()), 0), tx.Essence.Outputs[0]) + output := e.outputManager.CreateOutputFromAddress(wallet, receiveAddr, faucetTokensPerRequest, iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.ID()), 0), signedTx.Transaction.Outputs[0]) // set remainder output to be reused by the faucet wallet e.faucet.AddUnspentOutput(&Output{ - OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(tx.ID()), 1), + OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.ID()), 1), Address: faucetAddr, Index: 0, - Balance: tx.Essence.Outputs[1].BaseTokenAmount(), - OutputStruct: tx.Essence.Outputs[1], + Balance: signedTx.Transaction.Outputs[1].BaseTokenAmount(), + OutputStruct: signedTx.Transaction.Outputs[1], }) return output, nil @@ -325,18 +325,18 @@ func (e *EvilWallet) splitOutputs(splitOutput *Output, inputWallet, outputWallet input, outputs := e.handleInputOutputDuringSplitOutputs(splitOutput, FaucetRequestSplitNumber, outputWallet) - tx, err := e.CreateTransaction(WithInputs(input), WithOutputs(outputs), WithIssuer(inputWallet), WithOutputWallet(outputWallet)) + signedTx, err := e.CreateTransaction(WithInputs(input), WithOutputs(outputs), WithIssuer(inputWallet), WithOutputWallet(outputWallet)) if err != nil { return iotago.TransactionID{}, err } - _, err = e.connector.GetClient().PostTransaction(tx) + _, err = e.connector.GetClient().PostTransaction(signedTx) if err != nil { fmt.Println(err) return iotago.TransactionID{}, err } - return lo.PanicOnErr(tx.ID()), nil + return lo.PanicOnErr(signedTx.ID()), nil } func (e *EvilWallet) handleInputOutputDuringSplitOutputs(splitOutput *Output, splitNumber int, receiveWallet *Wallet) (input *Output, outputs []*OutputOption) { @@ -364,11 +364,11 @@ func (e *EvilWallet) ClearAllAliases() { e.aliasManager.ClearAllAliases() } -func (e *EvilWallet) PrepareCustomConflicts(conflictsMaps []ConflictSlice) (conflictBatch [][]*iotago.Transaction, err error) { +func (e *EvilWallet) PrepareCustomConflicts(conflictsMaps []ConflictSlice) (conflictBatch [][]*iotago.SignedTransaction, err error) { for _, conflictMap := range conflictsMaps { - var txs []*iotago.Transaction - for _, options := range conflictMap { - tx, err2 := e.CreateTransaction(options...) + var txs []*iotago.SignedTransaction + for _, conflictOptions := range conflictMap { + tx, err2 := e.CreateTransaction(conflictOptions...) if err2 != nil { return nil, err2 } @@ -396,9 +396,9 @@ func (e *EvilWallet) SendCustomConflicts(conflictsMaps []ConflictSlice) (err err wg := sync.WaitGroup{} for i, tx := range txs { wg.Add(1) - go func(clt Client, tx *iotago.Transaction) { + go func(clt Client, signedTx *iotago.SignedTransaction) { defer wg.Done() - _, _ = clt.PostTransaction(tx) + _, _ = clt.PostTransaction(signedTx) }(clients[i], tx) } wg.Wait() @@ -414,7 +414,7 @@ func (e *EvilWallet) SendCustomConflicts(conflictsMaps []ConflictSlice) (err err // Inputs of the transaction are determined in three ways: // 1 - inputs are provided directly without associated alias, 2- alias is provided, and input is already stored in an alias manager, // 3 - alias is provided, and there are no inputs assigned in Alias manager, so aliases are assigned to next ready inputs from input wallet. -func (e *EvilWallet) CreateTransaction(options ...Option) (tx *iotago.Transaction, err error) { +func (e *EvilWallet) CreateTransaction(options ...Option) (signedTx *iotago.SignedTransaction, err error) { buildOptions, err := NewOptions(options...) if err != nil { return nil, err @@ -445,23 +445,23 @@ func (e *EvilWallet) CreateTransaction(options ...Option) (tx *iotago.Transactio } } - tx, err = e.makeTransaction(inputs, outputs, buildOptions.inputWallet) + signedTx, err = e.makeTransaction(inputs, outputs, buildOptions.inputWallet) if err != nil { return nil, err } - e.addOutputsToOutputManager(tx, buildOptions.outputWallet, tempWallet, tempAddresses) - e.registerOutputAliases(tx, addrAliasMap) + e.addOutputsToOutputManager(signedTx, buildOptions.outputWallet, tempWallet, tempAddresses) + e.registerOutputAliases(signedTx, addrAliasMap) return } // addOutputsToOutputManager adds output to the OutputManager if. -func (e *EvilWallet) addOutputsToOutputManager(tx *iotago.Transaction, outWallet, tmpWallet *Wallet, tempAddresses map[string]types.Empty) { - for idx, o := range tx.Essence.Outputs { +func (e *EvilWallet) addOutputsToOutputManager(signedTx *iotago.SignedTransaction, outWallet, tmpWallet *Wallet, tempAddresses map[string]types.Empty) { + for idx, o := range signedTx.Transaction.Outputs { addr := o.UnlockConditionSet().Address().Address out := &Output{ - OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(tx.ID()), uint16(idx)), + OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.ID()), uint16(idx)), Address: addr, Balance: o.BaseTokenAmount(), OutputStruct: o, @@ -498,13 +498,13 @@ func (e *EvilWallet) updateInputWallet(buildOptions *Options) error { return nil } -func (e *EvilWallet) registerOutputAliases(tx *iotago.Transaction, addrAliasMap map[string]string) { +func (e *EvilWallet) registerOutputAliases(signedTx *iotago.SignedTransaction, addrAliasMap map[string]string) { if len(addrAliasMap) == 0 { return } - for idx := range tx.Essence.Outputs { - id := iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(tx.ID()), uint16(idx)) + for idx := range signedTx.Transaction.Outputs { + id := iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.ID()), uint16(idx)) out := e.outputManager.GetOutput(id) // register output alias @@ -707,7 +707,7 @@ func (e *EvilWallet) updateOutputBalances(buildOptions *Options) (err error) { return } -func (e *EvilWallet) makeTransaction(inputs []*Output, outputs iotago.Outputs[iotago.Output], w *Wallet) (tx *iotago.Transaction, err error) { +func (e *EvilWallet) makeTransaction(inputs []*Output, outputs iotago.Outputs[iotago.Output], w *Wallet) (tx *iotago.SignedTransaction, err error) { clt := e.Connector().GetClient() txBuilder := builder.NewTransactionBuilder(clt.CurrentAPI()) @@ -741,9 +741,9 @@ func (e *EvilWallet) makeTransaction(inputs []*Output, outputs iotago.Outputs[io return txBuilder.Build(iotago.NewInMemoryAddressSigner(walletKeys...)) } -func (e *EvilWallet) PrepareCustomConflictsSpam(scenario *EvilScenario) (txs [][]*iotago.Transaction, allAliases ScenarioAlias, err error) { +func (e *EvilWallet) PrepareCustomConflictsSpam(scenario *EvilScenario) (signedTxs [][]*iotago.SignedTransaction, allAliases ScenarioAlias, err error) { conflicts, allAliases := e.prepareConflictSliceForScenario(scenario) - txs, err = e.PrepareCustomConflicts(conflicts) + signedTxs, err = e.PrepareCustomConflicts(conflicts) return } diff --git a/tools/evil-spammer/wallet/output_manager.go b/tools/evil-spammer/wallet/output_manager.go index 1ab6ffe47..559c8521f 100644 --- a/tools/evil-spammer/wallet/output_manager.go +++ b/tools/evil-spammer/wallet/output_manager.go @@ -239,7 +239,7 @@ func (o *OutputManager) RequestOutputsByTxID(txID iotago.TransactionID) (outputI return } - for index := range tx.Essence.Outputs { + for index := range tx.Transaction.Outputs { outputIDs = append(outputIDs, iotago.OutputIDFromTransactionIDAndIndex(txID, uint16(index))) } diff --git a/tools/evil-spammer/wallet/wallet.go b/tools/evil-spammer/wallet/wallet.go index f31fa9a9e..c1c024a81 100644 --- a/tools/evil-spammer/wallet/wallet.go +++ b/tools/evil-spammer/wallet/wallet.go @@ -72,7 +72,8 @@ func (w *Wallet) Address() *iotago.Ed25519Address { index := uint64(w.lastAddrIdxUsed.Add(1)) hdWallet := mock.NewHDWallet("", w.seed[:], index) - addr := hdWallet.Address() + //nolint:forcetypeassert + addr := hdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address) w.indexAddrMap[index] = addr.String() w.addrIndexMap[addr.String()] = index @@ -85,7 +86,8 @@ func (w *Wallet) AddressOnIndex(index uint64) *iotago.Ed25519Address { defer w.Unlock() hdWallet := mock.NewHDWallet("", w.seed[:], index) - addr := hdWallet.Address() + //nolint:forcetypeassert + addr := hdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address) return addr } diff --git a/tools/gendoc/go.mod b/tools/gendoc/go.mod index edc8fc455..159e19742 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-20230927122328-da2eaee8d805 + github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729 github.com/iotaledger/hive.go/apputils v0.0.0-20230829152614-7afc7a4d89b3 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 ) @@ -18,6 +18,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -57,22 +58,21 @@ 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-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927112840-e982cb6707c9 // indirect - github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230925152824-4bfa09b8c132 // indirect - github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f // indirect + github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 // 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-20230929090257-1620d009ba8c // 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 @@ -134,6 +134,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pokt-network/smt v0.6.1 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect @@ -149,6 +150,7 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.8.4 // indirect github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect @@ -178,5 +180,6 @@ require ( google.golang.org/grpc v1.58.2 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect ) diff --git a/tools/gendoc/go.sum b/tools/gendoc/go.sum index ffe955242..8a69e6b1b 100644 --- a/tools/gendoc/go.sum +++ b/tools/gendoc/go.sum @@ -279,42 +279,40 @@ 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-20230927122328-da2eaee8d805 h1:OtCoTjJlQeICgv+MitK/okK9TldywK7jue8jI8k78eg= -github.com/iotaledger/hive.go/ads v0.0.0-20230927122328-da2eaee8d805/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805 h1:9JZsyrQHMWoaDmcw5ssgQn8YMFix2cOE36ha7DGhY2A= -github.com/iotaledger/hive.go/app v0.0.0-20230927122328-da2eaee8d805/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 h1:HHxgNhbtD6WDCwSQBbPrQe8c4ZNjNi0KcgCJo0nm9bY= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729 h1:rBADf+IZDKkDOuZznwIdonxF9jcOSQJU/qOYSNInX84= +github.com/iotaledger/hive.go/app v0.0.0-20230928074706-d58e32f86729/go.mod h1:eiZgbcwTDZ7d9hEait2EAwAhixWhceW4MXmuVk2EcEw= 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-20230927122328-da2eaee8d805 h1:2vSacMbBgQSAD+sNptWJQrJchIS+j9gEABYSYlUulg0= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 h1:vfY5UFZeybxNTB5NYJAcQxxngSmnWMkemB5C6KKcG+Y= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 h1:teasrvb1DqJqOcVAxH15ZdGIPdNHI+lCU9OOrPBfHVc= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 h1:pj5K1GCyW8ugsL8QXHGkNmWEucoY3yJC/W5uBwxXEvQ= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 h1:heT6TrgjINpwnmUMo7uDJ5vdEpuStDIbDWcCdbTl6+I= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 h1:aFd/nvj8qkO+6qwaaUFwbfD4z9LhHZiDMFKzAzEZaE0= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 h1:aeJ/8Q6qw1fC6Mf3SGLwDwy2ZWVdG4q/9zNbKElVXmU= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 h1:i4DN1/Pbzd/QhbGddRPO8N18ZwrB7yzkFLHjgx1unk8= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805/go.mod h1:UF7PzlWdZ2H0Hkxrt4AgJmNVeMXUJzw4RwbHpib1DB0= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 h1:35L6o/GmpOy8GrcsnNSvBR1/Cqzt60Qt/4DniPCOOZY= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 h1:9UoQ4V2NxrUHT4m+LL1/PmexuZYpelDlaLBEimO5w+k= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 h1:2ls3eCyGrHaHEYMxKsdd6S5pmjAzwUrOG2G5O4dsJp0= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 h1:dXXdK66EE7/2/lgfmwU0J+avEYLryKe0Kpn63Kmn+xo= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927112840-e982cb6707c9 h1:vRGNfCcC7xwqQP0WKNQrtfBarx4y3tTnpfljmgOTMG4= -github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927112840-e982cb6707c9/go.mod h1:KbmEuxbhax3fyVrxF4RjBD1/MWLFxHLNDFBnDYUzok4= -github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230925152824-4bfa09b8c132 h1:YHvgNY3/TRx84UxqizkFe7vVUxAMQB2DOuEL8wjHxpg= -github.com/iotaledger/inx/go v1.0.0-rc.2.0.20230925152824-4bfa09b8c132/go.mod h1:DIFr5lt73HLIyn/Lg2jtzfakwhIT0mMZjMFFji3GXeI= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f h1:b7mr4pVMRsqp4BMXFA6GR911t/10AmvZIjsvgLJegRQ= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 h1:PQ9TFyXBrV6LLTOzE43CV/vz+ItN5v6lcA7ms0YOvcE= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 h1:mwIZhduBiOD4rG4hqrPhW616EU1wX4eD2zHu26be5Yc= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 h1:FpFlPNOHcvHDyk1gN3OuL/hgvTKVsc5IN+q8U1YF9P4= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 h1:hHdIZn95+HdP1JdjV8TAsuL5kU4eb4gncehyjXo/feQ= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 h1:+/OtOAx2tMy8ER3XBt9RpnspWyDrVqW6kQGAd24jT0k= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 h1:XCYvP8XwETTXF5LNz8q9X3EajDut7+UwTwqJ2TQ0TJo= +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-20230928074706-d58e32f86729 h1:hW4r9no+03ufp2fyx4IjTFwINkEz3OI3LqvSjv7SJ1c= +github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729 h1:FOQetJY2scpCtCGrZQWGw3RwB3lRIDdyu+M6P1NACM4= +github.com/iotaledger/hive.go/logger v0.0.0-20230928074706-d58e32f86729/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 h1:4aRR9UG4dHpdlTcMN1Px++eaxlGXXk1n6co8t/WlchM= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 h1:mPmP3/0XJAf0ZkCzQenpoQPMv+m56Z8+A1i/UO18Hdw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 h1:gZlIK1OzdA3aZ78PsiWe3poVzawyw4S3zboMHE1TrY0= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/inx-app v1.0.0-rc.3.0.20230927140518-622f63be6182 h1:lQiktl3Q0B+cHbVum7WzJikOEP+buw686oSrw5Unyz8= +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-20230929090257-1620d009ba8c h1:faTwv2r4EZ6FixcFtaSD5M02YRm+/kmQKsLBsYSJl3I= +github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= 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 171879255..43f5de5bf 100644 --- a/tools/genesis-snapshot/go.mod +++ b/tools/genesis-snapshot/go.mod @@ -5,12 +5,12 @@ go 1.21 replace github.com/iotaledger/iota-core => ../../ require ( - github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 - github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 + github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729 + github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 - github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f + github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c github.com/mr-tron/base58 v1.2.0 github.com/spf13/pflag v1.0.5 golang.org/x/crypto v0.13.0 @@ -27,15 +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-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 // indirect - github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 // indirect + github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 // indirect + github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 // 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 @@ -61,8 +59,6 @@ require ( github.com/wollac/iota-crypto-demo v0.0.0-20221117162917-b10619eccb98 // indirect github.com/zyedidia/generic v1.2.1 // indirect go.uber.org/atomic v1.11.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/sys v0.12.0 // indirect google.golang.org/protobuf v1.31.0 // indirect diff --git a/tools/genesis-snapshot/go.sum b/tools/genesis-snapshot/go.sum index 7eadbb7cd..ef08c5fab 100644 --- a/tools/genesis-snapshot/go.sum +++ b/tools/genesis-snapshot/go.sum @@ -28,34 +28,30 @@ 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-20230927122328-da2eaee8d805 h1:OtCoTjJlQeICgv+MitK/okK9TldywK7jue8jI8k78eg= -github.com/iotaledger/hive.go/ads v0.0.0-20230927122328-da2eaee8d805/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805 h1:2vSacMbBgQSAD+sNptWJQrJchIS+j9gEABYSYlUulg0= -github.com/iotaledger/hive.go/constraints v0.0.0-20230927122328-da2eaee8d805/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805 h1:vfY5UFZeybxNTB5NYJAcQxxngSmnWMkemB5C6KKcG+Y= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230927122328-da2eaee8d805/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805 h1:teasrvb1DqJqOcVAxH15ZdGIPdNHI+lCU9OOrPBfHVc= -github.com/iotaledger/hive.go/crypto v0.0.0-20230927122328-da2eaee8d805/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805 h1:pj5K1GCyW8ugsL8QXHGkNmWEucoY3yJC/W5uBwxXEvQ= -github.com/iotaledger/hive.go/ds v0.0.0-20230927122328-da2eaee8d805/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805 h1:heT6TrgjINpwnmUMo7uDJ5vdEpuStDIbDWcCdbTl6+I= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230927122328-da2eaee8d805/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805 h1:aFd/nvj8qkO+6qwaaUFwbfD4z9LhHZiDMFKzAzEZaE0= -github.com/iotaledger/hive.go/kvstore v0.0.0-20230927122328-da2eaee8d805/go.mod h1:DeP4JF4N995LteD0+/o7NsW1bO5IXURIJ27A69Ca5+Y= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805 h1:aeJ/8Q6qw1fC6Mf3SGLwDwy2ZWVdG4q/9zNbKElVXmU= -github.com/iotaledger/hive.go/lo v0.0.0-20230927122328-da2eaee8d805/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805 h1:i4DN1/Pbzd/QhbGddRPO8N18ZwrB7yzkFLHjgx1unk8= -github.com/iotaledger/hive.go/log v0.0.0-20230927122328-da2eaee8d805/go.mod h1:UF7PzlWdZ2H0Hkxrt4AgJmNVeMXUJzw4RwbHpib1DB0= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805 h1:35L6o/GmpOy8GrcsnNSvBR1/Cqzt60Qt/4DniPCOOZY= -github.com/iotaledger/hive.go/logger v0.0.0-20230927122328-da2eaee8d805/go.mod h1:sxqWRdZ1OOxwkxVczuGcW034Mpt2vFh5ebJHO++ZYeI= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805 h1:9UoQ4V2NxrUHT4m+LL1/PmexuZYpelDlaLBEimO5w+k= -github.com/iotaledger/hive.go/runtime v0.0.0-20230927122328-da2eaee8d805/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805 h1:2ls3eCyGrHaHEYMxKsdd6S5pmjAzwUrOG2G5O4dsJp0= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230927122328-da2eaee8d805/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805 h1:dXXdK66EE7/2/lgfmwU0J+avEYLryKe0Kpn63Kmn+xo= -github.com/iotaledger/hive.go/stringify v0.0.0-20230927122328-da2eaee8d805/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f h1:b7mr4pVMRsqp4BMXFA6GR911t/10AmvZIjsvgLJegRQ= -github.com/iotaledger/iota.go/v4 v4.0.0-20230927112835-2dc846c6153f/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729 h1:HHxgNhbtD6WDCwSQBbPrQe8c4ZNjNi0KcgCJo0nm9bY= +github.com/iotaledger/hive.go/ads v0.0.0-20230928074706-d58e32f86729/go.mod h1:IAWZ/5It5P8B41mWyJXJVcG0vuikVRaTFKQnr2D2q+c= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729 h1:PQ9TFyXBrV6LLTOzE43CV/vz+ItN5v6lcA7ms0YOvcE= +github.com/iotaledger/hive.go/constraints v0.0.0-20230928074706-d58e32f86729/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729 h1:mwIZhduBiOD4rG4hqrPhW616EU1wX4eD2zHu26be5Yc= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230928074706-d58e32f86729/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729 h1:FpFlPNOHcvHDyk1gN3OuL/hgvTKVsc5IN+q8U1YF9P4= +github.com/iotaledger/hive.go/crypto v0.0.0-20230928074706-d58e32f86729/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729 h1:hHdIZn95+HdP1JdjV8TAsuL5kU4eb4gncehyjXo/feQ= +github.com/iotaledger/hive.go/ds v0.0.0-20230928074706-d58e32f86729/go.mod h1:ZrqsjIJS2QCgGp7Ki+l4hWJQgzfBObUCemb5Upwlx18= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729 h1:+/OtOAx2tMy8ER3XBt9RpnspWyDrVqW6kQGAd24jT0k= +github.com/iotaledger/hive.go/ierrors v0.0.0-20230928074706-d58e32f86729/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/kvstore v0.0.0-20230928074706-d58e32f86729 h1:XCYvP8XwETTXF5LNz8q9X3EajDut7+UwTwqJ2TQ0TJo= +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-20230928074706-d58e32f86729 h1:hW4r9no+03ufp2fyx4IjTFwINkEz3OI3LqvSjv7SJ1c= +github.com/iotaledger/hive.go/lo v0.0.0-20230928074706-d58e32f86729/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729 h1:4aRR9UG4dHpdlTcMN1Px++eaxlGXXk1n6co8t/WlchM= +github.com/iotaledger/hive.go/runtime v0.0.0-20230928074706-d58e32f86729/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729 h1:mPmP3/0XJAf0ZkCzQenpoQPMv+m56Z8+A1i/UO18Hdw= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230928074706-d58e32f86729/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729 h1:gZlIK1OzdA3aZ78PsiWe3poVzawyw4S3zboMHE1TrY0= +github.com/iotaledger/hive.go/stringify v0.0.0-20230928074706-d58e32f86729/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c h1:faTwv2r4EZ6FixcFtaSD5M02YRm+/kmQKsLBsYSJl3I= +github.com/iotaledger/iota.go/v4 v4.0.0-20230929090257-1620d009ba8c/go.mod h1:wR9xBbsofns9hFyRHFZ2bDYIb861qsfmQPVMBKcPvDo= 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= @@ -113,7 +109,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -125,12 +120,6 @@ github.com/zyedidia/generic v1.2.1 h1:Zv5KS/N2m0XZZiuLS82qheRG4X1o5gsWreGb0hR7XD github.com/zyedidia/generic v1.2.1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= diff --git a/tools/genesis-snapshot/presets/presets.go b/tools/genesis-snapshot/presets/presets.go index e912e7b29..dbfee7494 100644 --- a/tools/genesis-snapshot/presets/presets.go +++ b/tools/genesis-snapshot/presets/presets.go @@ -23,10 +23,10 @@ var Base = []options.Option[snapshotcreator.Options]{ iotago.WithNetworkOptions("default", "rms"), iotago.WithSupplyOptions(10_000_000_000, 100, 1, 10, 100, 100, 100), iotago.WithTimeProviderOptions(time.Now().Unix(), 10, 13), - iotago.WithLivenessOptions(5, 7, 14, 30), + iotago.WithLivenessOptions(30, 30, 7, 14, 30), // increase/decrease threshold = fraction * slotDurationInSeconds * schedulerRate iotago.WithCongestionControlOptions(500, 500, 500, 800000, 500000, 100000, 1, 1000, 100), - iotago.WithWorkScoreOptions(25, 1, 10, 100, 50, 10, 10, 50, 1, 10, 250, 2), + iotago.WithWorkScoreOptions(25, 1, 100, 50, 10, 10, 50, 1, 10, 250), ), ), snapshotcreator.WithRootBlocks(map[iotago.BlockID]iotago.CommitmentID{ @@ -43,7 +43,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinValidatorAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0x293dc170d9a59474e6d81cfba7f7d924c09b25d7166bcfba606e53114d0a758b")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: 1, StakedAmount: testsuite.MinValidatorAccountAmount, @@ -55,7 +55,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinValidatorAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0x05c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: 1, StakedAmount: testsuite.MinValidatorAccountAmount, @@ -67,7 +67,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinValidatorAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0x1e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: 1, StakedAmount: testsuite.MinValidatorAccountAmount, @@ -79,7 +79,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinIssuerAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0xa54fafa44a88e4a6a37796526ea884f613a24d84337871226eb6360f022d8b39")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, Mana: iotago.Mana(testsuite.MinIssuerAccountAmount), }, snapshotcreator.AccountDetails{ // nomana2 @@ -88,7 +88,7 @@ var Docker = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinIssuerAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0xcb5ea14175ce649149ee41217c44aa70c3205b9939968449eae408727a71f91b")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, Mana: iotago.Mana(testsuite.MinIssuerAccountAmount), }, ), @@ -97,10 +97,10 @@ var Docker = []options.Option[snapshotcreator.Options]{ iotago.WithNetworkOptions("docker", "rms"), iotago.WithSupplyOptions(10_000_000_000, 1, 1, 10, 100, 100, 100), iotago.WithTimeProviderOptions(time.Now().Unix(), 10, 13), - iotago.WithLivenessOptions(5, 7, 14, 30), + iotago.WithLivenessOptions(30, 30, 7, 14, 30), // increase/decrease threshold = fraction * slotDurationInSeconds * schedulerRate iotago.WithCongestionControlOptions(500, 500, 500, 800000, 500000, 100000, 1, 1000, 100), - iotago.WithWorkScoreOptions(25, 1, 10, 100, 50, 10, 10, 50, 1, 10, 250, 2), + iotago.WithWorkScoreOptions(25, 1, 100, 50, 10, 10, 50, 1, 10, 250), ), ), } @@ -115,7 +115,7 @@ var Feature = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinValidatorAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0x01fb6b9db5d96240aef00bc950d1c67a6494513f6d7cf784e57b4972b96ab2fe")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: 1, StakedAmount: testsuite.MinValidatorAccountAmount, @@ -127,7 +127,7 @@ var Feature = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinValidatorAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0x83e7f71a440afd48981a8b4684ddae24434b7182ce5c47cfb56ac528525fd4b6")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: 1, StakedAmount: testsuite.MinValidatorAccountAmount, @@ -139,7 +139,7 @@ var Feature = []options.Option[snapshotcreator.Options]{ Amount: testsuite.MinValidatorAccountAmount, IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(lo.PanicOnErr(hexutil.DecodeHex("0xac628986b2ef52a1679f2289fcd7b4198476976dea4c30ae34ff04ae52e14805")))), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: iotago.BlockIssuanceCredits(iotago.MaxBlockIssuanceCredits), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: 1, StakedAmount: testsuite.MinValidatorAccountAmount, @@ -151,10 +151,10 @@ var Feature = []options.Option[snapshotcreator.Options]{ iotago.WithNetworkOptions("feature", "rms"), iotago.WithSupplyOptions(10_000_000_000, 100, 1, 10, 100, 100, 100), iotago.WithTimeProviderOptions(1689848996, 10, 13), - iotago.WithLivenessOptions(5, 10, 20, 30), + iotago.WithLivenessOptions(30, 30, 10, 20, 30), // increase/decrease threshold = fraction * slotDurationInSeconds * schedulerRate iotago.WithCongestionControlOptions(500, 500, 500, 800000, 500000, 100000, 1, 1000, 100), - iotago.WithWorkScoreOptions(25, 1, 10, 100, 50, 10, 10, 50, 1, 10, 250, 2), + iotago.WithWorkScoreOptions(25, 1, 100, 50, 10, 10, 50, 1, 10, 250), ), ), }