diff --git a/.github/workflows/feature-network-deploy.yml b/.github/workflows/feature-network-deploy.yml index c4c71e425..812411683 100644 --- a/.github/workflows/feature-network-deploy.yml +++ b/.github/workflows/feature-network-deploy.yml @@ -70,7 +70,7 @@ jobs: - name: Ansible deploy env: CUSTOM_SNAPSHOT_URL: '${{ github.event.inputs.snapshotUrl }}' - DEFAULT_SNAPSHOT_URL: 'https://0x0.st/HJXh.bin' + DEFAULT_SNAPSHOT_URL: 'https://0x0.st/HywH.bin' NETWORK_ENVIRONMENT: '${{ secrets.NETWORK_ENVIRONMENT }}' IOTA_CORE_DOCKER_IMAGE_REPO: 'iotaledger/iota-core' IOTA_CORE_DOCKER_IMAGE_TAG: 'feature' diff --git a/.gitignore b/.gitignore index fea8c46c9..56ae79587 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,7 @@ iota-core # IDE related files .vscode/ .idea/ -go.work -go.work.sum +go.work* # dist packages dist/ diff --git a/components/app/app.go b/components/app/app.go index 5c4b42957..5f840eb4c 100644 --- a/components/app/app.go +++ b/components/app/app.go @@ -17,7 +17,6 @@ import ( "github.com/iotaledger/iota-core/components/protocol" "github.com/iotaledger/iota-core/components/restapi" coreapi "github.com/iotaledger/iota-core/components/restapi/core" - "github.com/iotaledger/iota-core/components/validator" "github.com/iotaledger/iota-core/pkg/toolset" ) @@ -48,7 +47,6 @@ Command line flags: debugapi.Component, metricstracker.Component, protocol.Component, - validator.Component, dashboardmetrics.Component, dashboard.Component, metrics.Component, diff --git a/components/dashboard/component.go b/components/dashboard/component.go index 62326f082..360702aaa 100644 --- a/components/dashboard/component.go +++ b/components/dashboard/component.go @@ -155,7 +155,7 @@ func currentNodeStatus() *nodestatus { status.TangleTime = tangleTime{ Synced: syncStatus.NodeSynced, - Bootstrapped: deps.Protocol.MainEngineInstance().SyncManager.IsBootstrapped(), + Bootstrapped: syncStatus.NodeBootstrapped, AcceptedBlockSlot: int64(syncStatus.LastAcceptedBlockSlot), ConfirmedBlockSlot: int64(syncStatus.LastConfirmedBlockSlot), CommittedSlot: int64(syncStatus.LatestCommitment.Slot()), diff --git a/components/inx/server_accounts.go b/components/inx/server_accounts.go new file mode 100644 index 000000000..6e8585be6 --- /dev/null +++ b/components/inx/server_accounts.go @@ -0,0 +1,53 @@ +package inx + +import ( + "context" + + "github.com/iotaledger/hive.go/ierrors" + inx "github.com/iotaledger/inx/go" + iotago "github.com/iotaledger/iota.go/v4" +) + +func (s *Server) ReadIsValidatorAccount(_ context.Context, accountInfoRequest *inx.AccountInfoRequest) (*inx.BoolResponse, error) { + slot := iotago.SlotIndex(accountInfoRequest.GetAccountSlot()) + accountID, _, err := iotago.AccountIDFromBytes(accountInfoRequest.AccountId) + if err != nil { + return nil, ierrors.Wrap(err, "error when parsing account id") + } + + account, exists, err := deps.Protocol.MainEngineInstance().Ledger.Account(accountID, slot) + if err != nil { + return nil, ierrors.Wrapf(err, "error when retrieving account data for %s", accountID) + } + + return inx.WrapBoolResponse(exists && account.StakeEndEpoch <= deps.Protocol.APIForSlot(slot).TimeProvider().EpochFromSlot(slot)), nil +} + +func (s *Server) ReadIsCommitteeMember(_ context.Context, accountInfoRequest *inx.AccountInfoRequest) (*inx.BoolResponse, error) { + slot := iotago.SlotIndex(accountInfoRequest.GetAccountSlot()) + accountID, _, err := iotago.AccountIDFromBytes(accountInfoRequest.AccountId) + if err != nil { + return nil, ierrors.Wrap(err, "error when parsing account id") + } + committee, exists := deps.Protocol.MainEngineInstance().SybilProtection.SeatManager().CommitteeInSlot(slot) + if !exists { + return nil, ierrors.Errorf("committee does not exist for slot %d", slot) + } + + return inx.WrapBoolResponse(committee.HasAccount(accountID)), nil +} + +func (s *Server) ReadIsCandidate(_ context.Context, accountInfoRequest *inx.AccountInfoRequest) (*inx.BoolResponse, error) { + slot := iotago.SlotIndex(accountInfoRequest.GetAccountSlot()) + accountID, _, err := iotago.AccountIDFromBytes(accountInfoRequest.AccountId) + if err != nil { + return nil, ierrors.Wrap(err, "error when parsing account id") + } + + isCandidateActive, err := deps.Protocol.MainEngineInstance().SybilProtection.IsCandidateActive(accountID, deps.Protocol.APIForSlot(slot).TimeProvider().EpochFromSlot(slot)) + if err != nil { + return nil, ierrors.Wrap(err, "error when checking if candidate is active") + } + + return inx.WrapBoolResponse(isCandidateActive), nil +} diff --git a/components/inx/server_blocks.go b/components/inx/server_blocks.go index 63b6b076e..0565e94b8 100644 --- a/components/inx/server_blocks.go +++ b/components/inx/server_blocks.go @@ -16,6 +16,12 @@ import ( iotago "github.com/iotaledger/iota.go/v4" ) +func (s *Server) ReadActiveRootBlocks(_ context.Context, _ *inx.NoParams) (*inx.RootBlocksResponse, error) { + activeRootBlocks := deps.Protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() + + return inx.WrapRootBlocks(activeRootBlocks), nil +} + func (s *Server) ReadBlock(_ context.Context, blockID *inx.BlockId) (*inx.RawBlock, error) { blkID := blockID.Unwrap() block, exists := deps.Protocol.MainEngineInstance().Block(blkID) // block +1 diff --git a/components/inx/server_commitments.go b/components/inx/server_commitments.go index 7dd44ba84..b16713f48 100644 --- a/components/inx/server_commitments.go +++ b/components/inx/server_commitments.go @@ -22,6 +22,14 @@ func inxCommitment(commitment *model.Commitment) *inx.Commitment { } } +func (s *Server) ForceCommitUntil(_ context.Context, slot *inx.SlotIndex) (*inx.NoParams, error) { + err := deps.Protocol.MainEngineInstance().Notarization.ForceCommitUntil(slot.Unwrap()) + if err != nil { + return nil, ierrors.Wrapf(err, "error while performing force commit until %d", slot.Index) + } + + return &inx.NoParams{}, nil +} func (s *Server) ReadCommitment(_ context.Context, req *inx.CommitmentRequest) (*inx.Commitment, error) { commitmentSlot := iotago.SlotIndex(req.GetCommitmentSlot()) diff --git a/components/inx/server_node.go b/components/inx/server_node.go index 9a2f8386e..0039cad2b 100644 --- a/components/inx/server_node.go +++ b/components/inx/server_node.go @@ -25,6 +25,7 @@ func inxNodeStatus(status *syncmanager.SyncStatus) *inx.NodeStatus { return &inx.NodeStatus{ IsHealthy: status.NodeSynced, + IsBootstrapped: status.NodeBootstrapped, LastAcceptedBlockSlot: uint32(status.LastAcceptedBlockSlot), LastConfirmedBlockSlot: uint32(status.LastConfirmedBlockSlot), LatestCommitment: inxCommitment(status.LatestCommitment), diff --git a/components/validator/component.go b/components/validator/component.go deleted file mode 100644 index 5d8bb7926..000000000 --- a/components/validator/component.go +++ /dev/null @@ -1,93 +0,0 @@ -package validator - -import ( - "context" - "sync/atomic" - "time" - - "go.uber.org/dig" - - "github.com/iotaledger/hive.go/app" - "github.com/iotaledger/hive.go/runtime/event" - "github.com/iotaledger/hive.go/runtime/timed" - "github.com/iotaledger/iota-core/pkg/blockhandler" - "github.com/iotaledger/iota-core/pkg/daemon" - "github.com/iotaledger/iota-core/pkg/protocol" - "github.com/iotaledger/iota-core/pkg/protocol/engine/notarization" - iotago "github.com/iotaledger/iota.go/v4" -) - -func init() { - Component = &app.Component{ - Name: "Validator", - DepsFunc: func(cDeps dependencies) { deps = cDeps }, - Params: params, - Run: run, - IsEnabled: func(_ *dig.Container) bool { - return ParamsValidator.Enabled - }, - } -} - -var ( - Component *app.Component - deps dependencies - - isValidator atomic.Bool - executor *timed.TaskExecutor[iotago.AccountID] - validatorAccount blockhandler.Account -) - -type dependencies struct { - dig.In - - Protocol *protocol.Protocol - BlockHandler *blockhandler.BlockHandler -} - -func run() error { - validatorAccount = blockhandler.AccountFromParams(ParamsValidator.Account, ParamsValidator.PrivateKey) - - executor = timed.NewTaskExecutor[iotago.AccountID](1) - - return Component.Daemon().BackgroundWorker(Component.Name, func(ctx context.Context) { - Component.LogInfof("Starting Validator with IssuerID: %s", validatorAccount.ID()) - - checkValidatorStatus(ctx) - - deps.Protocol.Events.Engine.Notarization.SlotCommitted.Hook(func(details *notarization.SlotCommittedDetails) { - checkValidatorStatus(ctx) - }, event.WithWorkerPool(Component.WorkerPool)) - - <-ctx.Done() - - executor.Shutdown() - - Component.LogInfo("Stopping Validator... done") - }, daemon.PriorityActivity) -} - -func checkValidatorStatus(ctx context.Context) { - account, exists, err := deps.Protocol.MainEngineInstance().Ledger.Account(validatorAccount.ID(), deps.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot()) - if err != nil { - Component.LogErrorf("error when retrieving BlockIssuer account %s: %w", validatorAccount.ID(), err) - - return - } - - if !exists || account.StakeEndEpoch <= deps.Protocol.CommittedAPI().TimeProvider().EpochFromSlot(deps.Protocol.CommittedAPI().TimeProvider().SlotFromTime(time.Now())) { - if prevValue := isValidator.Swap(false); prevValue { - // If the account stops being a validator, don't issue any blocks. - Component.LogInfof("BlockIssuer account %s stopped being a validator", validatorAccount.ID()) - executor.Cancel(validatorAccount.ID()) - } - - return - } - - if prevValue := isValidator.Swap(true); !prevValue { - Component.LogInfof("BlockIssuer account %s became a validator", validatorAccount.ID()) - // If the account becomes a validator, start issue validator blocks. - executor.ExecuteAfter(validatorAccount.ID(), func() { issueValidatorBlock(ctx) }, ParamsValidator.CommitteeBroadcastInterval) - } -} diff --git a/components/validator/issuer.go b/components/validator/issuer.go deleted file mode 100644 index 038fb9e78..000000000 --- a/components/validator/issuer.go +++ /dev/null @@ -1,168 +0,0 @@ -package validator - -import ( - "context" - "time" - - "github.com/iotaledger/hive.go/ierrors" - "github.com/iotaledger/iota-core/pkg/model" - iotago "github.com/iotaledger/iota.go/v4" - "github.com/iotaledger/iota.go/v4/builder" -) - -var ErrBlockTooRecent = ierrors.New("block is too recent compared to latest commitment") - -func issueValidatorBlock(ctx context.Context) { - // Get the main engine instance in case it changes mid-execution. - engineInstance := deps.Protocol.MainEngineInstance() - - blockIssuingTime := time.Now() - nextBroadcast := blockIssuingTime.Add(ParamsValidator.CommitteeBroadcastInterval) - - // Use 'defer' because nextBroadcast is updated during function execution, and the value at the end needs to be used. - defer func() { - executor.ExecuteAt(validatorAccount.ID(), func() { issueValidatorBlock(ctx) }, nextBroadcast) - }() - - if !ParamsValidator.IgnoreBootstrapped && !engineInstance.SyncManager.IsBootstrapped() { - Component.LogDebug("Not issuing validator block because node is not bootstrapped yet.") - - return - } - - protocolParametersHash, err := deps.Protocol.CommittedAPI().ProtocolParameters().Hash() - if err != nil { - Component.LogWarnf("failed to get protocol parameters hash: %s", err.Error()) - - return - } - - parents := engineInstance.TipSelection.SelectTips(iotago.BlockTypeValidationMaxParents) - - addressableCommitment, err := getAddressableCommitment(deps.Protocol.CommittedAPI().TimeProvider().SlotFromTime(blockIssuingTime)) - if err != nil && ierrors.Is(err, ErrBlockTooRecent) { - commitment, parentID, reviveChainErr := reviveChain(blockIssuingTime) - if reviveChainErr != nil { - Component.LogError("error reviving chain: %s", reviveChainErr.Error()) - return - } - - addressableCommitment = commitment - parents = make(model.ParentReferences) - parents[iotago.StrongParentType] = []iotago.BlockID{parentID} - } else if err != nil { - Component.LogWarnf("error getting commitment: %s", err.Error()) - - return - } - - // create the validation block here using the validation block builder from iota.go - validationBlock, err := builder.NewValidationBlockBuilder(deps.Protocol.CommittedAPI()). - IssuingTime(blockIssuingTime). - ProtocolParametersHash(protocolParametersHash). - SlotCommitmentID(addressableCommitment.MustID()). - HighestSupportedVersion(deps.Protocol.LatestAPI().Version()). - LatestFinalizedSlot(engineInstance.SyncManager.LatestFinalizedSlot()). - StrongParents(parents[iotago.StrongParentType]). - WeakParents(parents[iotago.WeakParentType]). - ShallowLikeParents(parents[iotago.ShallowLikeParentType]). - Sign(validatorAccount.ID(), validatorAccount.PrivateKey()). - Build() - if err != nil { - Component.LogWarnf("error creating validation block: %s", err.Error()) - - return - } - - modelBlock, err := model.BlockFromBlock(validationBlock) - if err != nil { - Component.LogWarnf("error creating model block from validation block: %s", err.Error()) - - return - } - - blockSlot := deps.Protocol.CommittedAPI().TimeProvider().SlotFromTime(blockIssuingTime) - committee, exists := engineInstance.SybilProtection.SeatManager().CommitteeInSlot(blockSlot) - if !exists { - Component.LogWarnf("committee for slot %d not selected: %s", blockSlot, err.Error()) - - return - } - - if !committee.HasAccount(validatorAccount.ID()) { - // update nextBroadcast value here, so that this updated value is used in the `defer` - // callback to schedule issuing of the next block at a different interval than for committee members - nextBroadcast = blockIssuingTime.Add(ParamsValidator.CandidateBroadcastInterval) - } - - if err = deps.BlockHandler.SubmitBlock(modelBlock); err != nil { - Component.LogWarnf("error issuing validator block: %s", err.Error()) - - return - } - - Component.LogDebugf("Issued validator block: %s - commitment %s %d - latest finalized slot %d", modelBlock.ID(), modelBlock.ProtocolBlock().Header.SlotCommitmentID, modelBlock.ProtocolBlock().Header.SlotCommitmentID.Slot(), modelBlock.ProtocolBlock().Header.LatestFinalizedSlot) -} - -func reviveChain(issuingTime time.Time) (*iotago.Commitment, iotago.BlockID, error) { - lastCommittedSlot := deps.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() - apiForSlot := deps.Protocol.APIForSlot(lastCommittedSlot) - - // Get a rootblock as recent as possible for the parent. - parentBlockID := iotago.EmptyBlockID - for rootBlock := range deps.Protocol.MainEngineInstance().EvictionState.ActiveRootBlocks() { - if rootBlock.Slot() > parentBlockID.Slot() { - parentBlockID = rootBlock - } - - // Exit the loop if we found a rootblock in the last committed slot (which is the highest we can get). - if parentBlockID.Slot() == lastCommittedSlot { - break - } - } - - issuingSlot := apiForSlot.TimeProvider().SlotFromTime(issuingTime) - - // Force commitments until minCommittableAge relative to the block's issuing time. We basically "pretend" that - // this block was already accepted at the time of issuing so that we have a commitment to reference. - if issuingSlot < apiForSlot.ProtocolParameters().MinCommittableAge() { // Should never happen as we're beyond maxCommittableAge which is > minCommittableAge. - return nil, iotago.EmptyBlockID, ierrors.Errorf("issuing slot %d is smaller than min committable age %d", issuingSlot, apiForSlot.ProtocolParameters().MinCommittableAge()) - } - commitUntilSlot := issuingSlot - apiForSlot.ProtocolParameters().MinCommittableAge() - - if err := deps.Protocol.MainEngineInstance().Notarization.ForceCommitUntil(commitUntilSlot); err != nil { - return nil, iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to force commit until slot %d", commitUntilSlot) - } - - commitment, err := deps.Protocol.MainEngineInstance().Storage.Commitments().Load(commitUntilSlot) - if err != nil { - return nil, iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to commit until slot %d to revive chain", commitUntilSlot) - } - - return commitment.Commitment(), parentBlockID, nil -} - -func getAddressableCommitment(blockSlot iotago.SlotIndex) (*iotago.Commitment, error) { - protoParams := deps.Protocol.CommittedAPI().ProtocolParameters() - commitment := deps.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Commitment() - - if blockSlot > commitment.Slot+protoParams.MaxCommittableAge() { - return nil, ierrors.Wrapf(ErrBlockTooRecent, "can't issue block: block slot %d is too far in the future, latest commitment is %d", blockSlot, commitment.Slot) - } - - if blockSlot < commitment.Slot+protoParams.MinCommittableAge() { - if blockSlot < protoParams.MinCommittableAge() || commitment.Slot < protoParams.MinCommittableAge() { - return commitment, nil - } - - commitmentSlot := commitment.Slot - protoParams.MinCommittableAge() - loadedCommitment, err := deps.Protocol.MainEngineInstance().Storage.Commitments().Load(commitmentSlot) - if err != nil { - return nil, ierrors.Wrapf(err, "error loading valid commitment of slot %d according to minCommittableAge from storage", commitmentSlot) - } - - return loadedCommitment.Commitment(), nil - } - - return commitment, nil -} diff --git a/components/validator/params.go b/components/validator/params.go deleted file mode 100644 index 037498ab2..000000000 --- a/components/validator/params.go +++ /dev/null @@ -1,34 +0,0 @@ -package validator - -import ( - "time" - - "github.com/iotaledger/hive.go/app" -) - -// ParametersValidator contains the definition of the configuration parameters used by the Validator component. -type ParametersValidator struct { - // Enabled defines whether the Validator component is enabled. - Enabled bool `default:"false" usage:"whether the Validator component is enabled"` - // CommitteeBroadcastInterval the interval at which the node will broadcast its committee validator block. - CommitteeBroadcastInterval time.Duration `default:"500ms" usage:"the interval at which the node will broadcast its committee validator block"` - // CandidateBroadcastInterval the interval at which the node will broadcast its candidate validator block. - CandidateBroadcastInterval time.Duration `default:"30m" usage:"the interval at which the node will broadcast its candidate validator block"` - // ParentsCount is the number of parents that node will choose for its validator blocks. - ParentsCount int `default:"8" usage:"the number of parents that node will choose for its validator blocks"` - // IgnoreBootstrapped sets whether the Validator component should start issuing validator blocks before the main engine is bootstrapped. - IgnoreBootstrapped bool `default:"false" usage:"whether the Validator component should start issuing validator blocks before the main engine is bootstrapped"` - // Account the accountID of the account that will issue the blocks. - Account string `default:"" usage:"the accountID of the validator account that will issue the blocks"` - // PrivateKey the private key of the account that will issue the blocks. - PrivateKey string `default:"" usage:"the private key of the validator account that will issue the blocks"` -} - -// ParamsValidator contains the values of the configuration parameters used by the Activity component. -var ParamsValidator = &ParametersValidator{} - -var params = &app.ComponentParams{ - Params: map[string]any{ - "validator": ParamsValidator, - }, -} diff --git a/config_defaults.json b/config_defaults.json index f24471e14..f89cc121a 100644 --- a/config_defaults.json +++ b/config_defaults.json @@ -116,15 +116,6 @@ "useMetricPrefix": false } }, - "validator": { - "enabled": false, - "committeeBroadcastInterval": "500ms", - "candidateBroadcastInterval": "30m", - "parentsCount": 8, - "ignoreBootstrapped": false, - "account": "", - "privateKey": "" - }, "dashboard": { "enabled": true, "bindAddress": "0.0.0.0:8081", diff --git a/deploy/ansible/hosts/feature.yml b/deploy/ansible/hosts/feature.yml index ac8e44cfc..66e7b10ee 100644 --- a/deploy/ansible/hosts/feature.yml +++ b/deploy/ansible/hosts/feature.yml @@ -7,21 +7,19 @@ cores: internal_nodes: hosts: node-01.feature.shimmer.iota.cafe: - validatorAccount: "{{ NODE_01_ACCOUNTID }}" + validatorAccountAddress: "{{ NODE_01_VALIDATOR_ACCOUNTADDRESS }}" validatorPrvKey: "{{ NODE_01_VALIDATOR_PRIVKEY }}" - p2pIdentityPrvKey: "{{ NODE_01_P2PIDENTITYPRIVATEKEY }}" + p2pIdentityPrvKey: "{{ NODE_01_P2PIDENTITY_PRIVKEY }}" node-02.feature.shimmer.iota.cafe: - validatorAccount: "{{ NODE_02_ACCOUNTID }}" + validatorAccountAddress: "{{ NODE_02_VALIDATOR_ACCOUNTADDRESS }}" validatorPrvKey: "{{ NODE_02_VALIDATOR_PRIVKEY }}" - p2pIdentityPrvKey: "{{ NODE_02_P2PIDENTITYPRIVATEKEY }}" + p2pIdentityPrvKey: "{{ NODE_02_P2PIDENTITY_PRIVKEY }}" node-03.feature.shimmer.iota.cafe: - validatorAccount: "{{ NODE_03_ACCOUNTID }}" + validatorAccountAddress: "{{ NODE_03_VALIDATOR_ACCOUNTADDRESS }}" validatorPrvKey: "{{ NODE_03_VALIDATOR_PRIVKEY }}" - p2pIdentityPrvKey: "{{ NODE_03_P2PIDENTITYPRIVATEKEY }}" + p2pIdentityPrvKey: "{{ NODE_03_P2PIDENTITY_PRIVKEY }}" node-04.feature.shimmer.iota.cafe: - p2pIdentityPrvKey: "{{ NODE_04_P2PIDENTITYPRIVATEKEY }}" - blockissuerPrvKey: "{{ NODE_04_BLOCKISSUER_PRV_KEY }}" - faucetPrvKey: "{{ NODE_04_FAUCET_PRV_KEY }}" + p2pIdentityPrvKey: "{{ NODE_04_P2PIDENTITY_PRIVKEY }}" node-05.feature.shimmer.iota.cafe: - p2pIdentityPrvKey: "{{ NODE_05_P2PIDENTITYPRIVATEKEY }}" + p2pIdentityPrvKey: "{{ NODE_05_P2PIDENTITY_PRIVKEY }}" vars: diff --git a/deploy/ansible/roles/iota-core-node/templates/docker-compose-iota-core.yml.j2 b/deploy/ansible/roles/iota-core-node/templates/docker-compose-iota-core.yml.j2 index d3bc9d82b..40beab818 100644 --- a/deploy/ansible/roles/iota-core-node/templates/docker-compose-iota-core.yml.j2 +++ b/deploy/ansible/roles/iota-core-node/templates/docker-compose-iota-core.yml.j2 @@ -14,7 +14,7 @@ services: # IOTA-CORE Nodes # ################### - iota_core: + iota-core: image: {{iota_core_docker_image_repo}}:{{iota_core_docker_image_tag}} container_name: iota-core stop_grace_period: 1m @@ -49,14 +49,6 @@ services: --restAPI.bindAddress=0.0.0.0:14265 --database.path=/app/data/database --protocol.snapshot.path=/app/data/snapshot.bin - {% if 'node-01' in inventory_hostname or 'node-02' in inventory_hostname or 'node-03' in inventory_hostname %} - --validator.enabled=true - {% if 'node-01' in inventory_hostname %} - --validator.ignoreBootstrapped=true - {% endif %} - --validator.account={{validatorAccount}} - --validator.privateKey={{validatorPrvKey}} - {% endif %} --dashboard.bindAddress=0.0.0.0:8081 --metrics.bindAddress=iota-core:9311 --inx.enabled=true @@ -97,11 +89,11 @@ services: inx-indexer: condition: service_started environment: - - "BLOCKISSUER_PRV_KEY={{blockissuerPrvKey}}" + - "BLOCKISSUER_PRV_KEY={{NODE_04_BLOCKISSUER_PRIVKEY}}" command: > --inx.address=iota-core:9029 --restAPI.bindAddress=inx-blockissuer:9086 - --blockIssuer.accountAddress=rms1pqas0clgfsf8du9e6dw0yx9nwclqe0dd4f728pvgmcshpscm8r5mkddrrfc + --blockIssuer.accountAddress={{NODE_04_BLOCKISSUER_ACCOUNTADDRESS}} --blockIssuer.proofOfWork.targetTrailingZeros=5 inx-faucet: @@ -116,13 +108,30 @@ services: condition: service_started inx-blockissuer: condition: service_started - networks: - - iota-core ports: - "8091:8091/tcp" # Faucet Frontend environment: - - "FAUCET_PRV_KEY={{faucetPrvKey}}" + - "FAUCET_PRV_KEY={{NODE_04_FAUCET_PRIVKEY}}" command: > --inx.address=iota-core:9029 --faucet.bindAddress=0.0.0.0:8091 +{% endif %} + +{% if 'node-01' in inventory_hostname or 'node-02' in inventory_hostname or 'node-03' in inventory_hostname %} + inx-validator: + container_name: inx-validator + image: iotaledger/inx-validator:1.0-alpha + stop_grace_period: 1m + restart: unless-stopped + depends_on: + iota-core: + condition: service_started + environment: + - "VALIDATOR_PRV_KEY={{validatorPrvKey}}" + command: > + --inx.address=iota-core:9029 + {% if 'node-01' in inventory_hostname %} + --validator.ignoreBootstrapped=true + {% endif %} + --validator.accountAddress={{validatorAccountAddress}} {% endif %} \ No newline at end of file diff --git a/deploy/ansible/run.sh b/deploy/ansible/run.sh index 3d800611d..62ee4840f 100755 --- a/deploy/ansible/run.sh +++ b/deploy/ansible/run.sh @@ -17,22 +17,22 @@ elkElasticUser=$ELASTIC_USER elkElasticPassword=$ELASTIC_PASSWORD grafanaAdminPassword=$GRAFANA_ADMIN_PASSWORD -NODE_01_ACCOUNTID=$NODE_01_ACCOUNTID +NODE_01_VALIDATOR_ACCOUNTADDRESS=$NODE_01_VALIDATOR_ACCOUNTADDRESS NODE_01_VALIDATOR_PRIVKEY=$NODE_01_VALIDATOR_PRIVKEY -NODE_01_P2PIDENTITYPRIVATEKEY=$NODE_01_P2PIDENTITYPRIVATEKEY +NODE_01_P2PIDENTITY_PRIVKEY=$NODE_01_P2PIDENTITY_PRIVKEY -NODE_02_ACCOUNTID=$NODE_02_ACCOUNTID +NODE_02_VALIDATOR_ACCOUNTADDRESS=$NODE_02_VALIDATOR_ACCOUNTADDRESS NODE_02_VALIDATOR_PRIVKEY=$NODE_02_VALIDATOR_PRIVKEY -NODE_02_P2PIDENTITYPRIVATEKEY=$NODE_02_P2PIDENTITYPRIVATEKEY +NODE_02_P2PIDENTITY_PRIVKEY=$NODE_02_P2PIDENTITY_PRIVKEY -NODE_03_ACCOUNTID=$NODE_03_ACCOUNTID +NODE_03_VALIDATOR_ACCOUNTADDRESS=$NODE_03_VALIDATOR_ACCOUNTADDRESS NODE_03_VALIDATOR_PRIVKEY=$NODE_03_VALIDATOR_PRIVKEY -NODE_03_P2PIDENTITYPRIVATEKEY=$NODE_03_P2PIDENTITYPRIVATEKEY +NODE_03_P2PIDENTITY_PRIVKEY=$NODE_03_P2PIDENTITY_PRIVKEY -NODE_04_P2PIDENTITYPRIVATEKEY=$NODE_04_P2PIDENTITYPRIVATEKEY -NODE_04_BLOCKISSUER_PRV_KEY=$NODE_04_BLOCKISSUER_PRIVKEY -NODE_04_FAUCET_PRV_KEY=$NODE_04_FAUCET_PRIVKEY - -NODE_05_P2PIDENTITYPRIVATEKEY=$NODE_05_P2PIDENTITYPRIVATEKEY +NODE_04_BLOCKISSUER_ACCOUNTADDRESS=$NODE_04_BLOCKISSUER_ACCOUNTADDRESS +NODE_04_BLOCKISSUER_PRIVKEY=$NODE_04_BLOCKISSUER_PRIVKEY +NODE_04_FAUCET_PRIVKEY=$NODE_04_FAUCET_PRIVKEY +NODE_04_P2PIDENTITY_PRIVKEY=$NODE_04_P2PIDENTITY_PRIVKEY +NODE_05_P2PIDENTITY_PRIVKEY=$NODE_05_P2PIDENTITY_PRIVKEY" \ ${ARGS[@]:2} deploy/ansible/"${2:-deploy.yml}" diff --git a/documentation/docs/references/configuration.md b/documentation/docs/references/configuration.md index ba034fde1..b6b3d58e2 100644 --- a/documentation/docs/references/configuration.md +++ b/documentation/docs/references/configuration.md @@ -375,35 +375,7 @@ Example: } ``` -## 10. Validator - -| Name | Description | Type | Default value | -| -------------------------- | ------------------------------------------------------------------------------------------------------------ | ------- | ------------- | -| enabled | Whether the Validator component is enabled | boolean | false | -| committeeBroadcastInterval | The interval at which the node will broadcast its committee validator block | string | "500ms" | -| candidateBroadcastInterval | The interval at which the node will broadcast its candidate validator block | string | "30m" | -| parentsCount | The number of parents that node will choose for its validator blocks | int | 8 | -| ignoreBootstrapped | Whether the Validator component should start issuing validator blocks before the main engine is bootstrapped | boolean | false | -| account | The accountID of the validator account that will issue the blocks | string | "" | -| privateKey | The private key of the validator account that will issue the blocks | string | "" | - -Example: - -```json - { - "validator": { - "enabled": false, - "committeeBroadcastInterval": "500ms", - "candidateBroadcastInterval": "30m", - "parentsCount": 8, - "ignoreBootstrapped": false, - "account": "", - "privateKey": "" - } - } -``` - -## 11. Dashboard +## 10. Dashboard | Name | Description | Type | Default value | | --------------------------------- | --------------------------------------- | ------- | -------------- | @@ -445,7 +417,7 @@ Example: } ``` -## 12. Metrics +## 11. Metrics | Name | Description | Type | Default value | | --------------- | ---------------------------------------------------- | ------- | -------------- | @@ -469,7 +441,7 @@ Example: } ``` -## 13. Inx +## 12. Inx | Name | Description | Type | Default value | | ----------- | ------------------------------------------------------ | ------- | ---------------- | diff --git a/pkg/blockhandler/account.go b/pkg/blockhandler/account.go deleted file mode 100644 index 5d71cb86b..000000000 --- a/pkg/blockhandler/account.go +++ /dev/null @@ -1,70 +0,0 @@ -package blockhandler - -import ( - "crypto/ed25519" - "fmt" - - "github.com/iotaledger/hive.go/crypto" - iotago "github.com/iotaledger/iota.go/v4" -) - -// Account represents an account. -type Account interface { - // ID returns the accountID. - ID() iotago.AccountID - - // Address returns the account address. - Address() iotago.Address - - // PrivateKey returns the account private key for signing. - PrivateKey() ed25519.PrivateKey -} - -var _ Account = &Ed25519Account{} - -// Ed25519Account is an account that uses an Ed25519 key pair. -type Ed25519Account struct { - accountID iotago.AccountID - privateKey ed25519.PrivateKey -} - -// NewEd25519Account creates a new Ed25519Account. -func NewEd25519Account(accountID iotago.AccountID, privateKey ed25519.PrivateKey) *Ed25519Account { - return &Ed25519Account{ - accountID: accountID, - privateKey: privateKey, - } -} - -// ID returns the accountID. -func (e *Ed25519Account) ID() iotago.AccountID { - return e.accountID -} - -// Address returns the account address. -func (e *Ed25519Account) Address() iotago.Address { - ed25519PubKey, ok := e.privateKey.Public().(ed25519.PublicKey) - if !ok { - panic("invalid public key type") - } - - return iotago.Ed25519AddressFromPubKey(ed25519PubKey) -} - -// PrivateKey returns the account private key for signing. -func (e *Ed25519Account) PrivateKey() ed25519.PrivateKey { - return e.privateKey -} - -func AccountFromParams(accountHex, privateKey string) Account { - accountID, err := iotago.AccountIDFromHexString(accountHex) - if err != nil { - panic(fmt.Sprintln("invalid accountID hex string", err)) - } - privKey, err := crypto.ParseEd25519PrivateKeyFromString(privateKey) - if err != nil { - panic(fmt.Sprintln("invalid ed25519 private key string", err)) - } - - return NewEd25519Account(accountID, privKey) -} diff --git a/pkg/blockhandler/block_params.go b/pkg/blockhandler/block_params.go deleted file mode 100644 index 951f285c8..000000000 --- a/pkg/blockhandler/block_params.go +++ /dev/null @@ -1,122 +0,0 @@ -package blockhandler - -import ( - "time" - - "github.com/iotaledger/hive.go/runtime/options" - "github.com/iotaledger/iota-core/pkg/model" - iotago "github.com/iotaledger/iota.go/v4" -) - -type BlockHeaderParams struct { - ParentsCount int - References model.ParentReferences - SlotCommitment *iotago.Commitment - LatestFinalizedSlot *iotago.SlotIndex - IssuingTime *time.Time - ProtocolVersion *iotago.Version - Issuer Account -} -type BasicBlockParams struct { - BlockHeader *BlockHeaderParams - Payload iotago.Payload -} -type ValidatorBlockParams struct { - BlockHeader *BlockHeaderParams - HighestSupportedVersion *iotago.Version - ProtocolParametersHash *iotago.Identifier -} - -func WithParentsCount(parentsCount int) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - builder.ParentsCount = parentsCount - } -} - -func WithStrongParents(blockIDs ...iotago.BlockID) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - if builder.References == nil { - builder.References = make(model.ParentReferences) - } - - builder.References[iotago.StrongParentType] = blockIDs - } -} -func WithWeakParents(blockIDs ...iotago.BlockID) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - if builder.References == nil { - builder.References = make(model.ParentReferences) - } - - builder.References[iotago.WeakParentType] = blockIDs - } -} - -func WithShallowLikeParents(blockIDs ...iotago.BlockID) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - if builder.References == nil { - builder.References = make(model.ParentReferences) - } - - builder.References[iotago.ShallowLikeParentType] = blockIDs - } -} - -func WithSlotCommitment(commitment *iotago.Commitment) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - builder.SlotCommitment = commitment - } -} - -func WithLatestFinalizedSlot(commitmentIndex iotago.SlotIndex) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - builder.LatestFinalizedSlot = &commitmentIndex - } -} - -func WithIssuingTime(issuingTime time.Time) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - builder.IssuingTime = &issuingTime - } -} - -func WithProtocolVersion(version iotago.Version) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - builder.ProtocolVersion = &version - } -} -func WithIssuer(issuer Account) func(builder *BlockHeaderParams) { - return func(builder *BlockHeaderParams) { - builder.Issuer = issuer - } -} - -func WithValidationBlockHeaderOptions(opts ...options.Option[BlockHeaderParams]) func(builder *ValidatorBlockParams) { - return func(builder *ValidatorBlockParams) { - builder.BlockHeader = options.Apply(&BlockHeaderParams{}, opts) - } -} - -func WithBasicBlockHeader(opts ...options.Option[BlockHeaderParams]) func(builder *BasicBlockParams) { - return func(builder *BasicBlockParams) { - builder.BlockHeader = options.Apply(&BlockHeaderParams{}, opts) - } -} - -func WithPayload(payload iotago.Payload) func(builder *BasicBlockParams) { - return func(builder *BasicBlockParams) { - builder.Payload = payload - } -} - -func WithHighestSupportedVersion(highestSupportedVersion iotago.Version) func(builder *ValidatorBlockParams) { - return func(builder *ValidatorBlockParams) { - builder.HighestSupportedVersion = &highestSupportedVersion - } -} - -func WithProtocolParametersHash(protocolParametersHash iotago.Identifier) func(builder *ValidatorBlockParams) { - return func(builder *ValidatorBlockParams) { - builder.ProtocolParametersHash = &protocolParametersHash - } -} diff --git a/pkg/blockhandler/blockissuer.go b/pkg/blockhandler/blockhandler.go similarity index 100% rename from pkg/blockhandler/blockissuer.go rename to pkg/blockhandler/blockhandler.go diff --git a/pkg/protocol/engine/syncmanager/syncmanager.go b/pkg/protocol/engine/syncmanager/syncmanager.go index d251dec88..6f0c0cb53 100644 --- a/pkg/protocol/engine/syncmanager/syncmanager.go +++ b/pkg/protocol/engine/syncmanager/syncmanager.go @@ -38,6 +38,7 @@ type SyncManager interface { } type SyncStatus struct { + NodeBootstrapped bool NodeSynced bool LastAcceptedBlockSlot iotago.SlotIndex LastConfirmedBlockSlot iotago.SlotIndex diff --git a/pkg/protocol/engine/syncmanager/trivialsyncmanager/syncmanager.go b/pkg/protocol/engine/syncmanager/trivialsyncmanager/syncmanager.go index 8e93f69bd..38fd0bb00 100644 --- a/pkg/protocol/engine/syncmanager/trivialsyncmanager/syncmanager.go +++ b/pkg/protocol/engine/syncmanager/trivialsyncmanager/syncmanager.go @@ -139,6 +139,7 @@ func (s *SyncManager) SyncStatus() *syncmanager.SyncStatus { return &syncmanager.SyncStatus{ NodeSynced: s.IsNodeSynced(), + NodeBootstrapped: s.IsBootstrapped(), LastAcceptedBlockSlot: s.lastAcceptedBlockSlot, LastConfirmedBlockSlot: s.lastConfirmedBlockSlot, LatestCommitment: s.latestCommitment, diff --git a/pkg/protocol/sybilprotection/activitytracker/activitytrackerv1/activitytracker.go b/pkg/protocol/sybilprotection/activitytracker/activitytrackerv1/activitytracker.go index e167e2ff5..9a58b6680 100644 --- a/pkg/protocol/sybilprotection/activitytracker/activitytrackerv1/activitytracker.go +++ b/pkg/protocol/sybilprotection/activitytracker/activitytrackerv1/activitytracker.go @@ -77,7 +77,9 @@ func (a *ActivityTracker) MarkSeatActive(seat account.SeatIndex, id iotago.Accou func (a *ActivityTracker) markSeatInactive(seat account.SeatIndex) { a.lastActivities.Delete(seat) - a.onlineCommittee.Delete(seat) - a.Events.OnlineCommitteeSeatRemoved.Trigger(seat) + // Only trigger the event if online committee member is removed. + if a.onlineCommittee.Delete(seat) { + a.Events.OnlineCommitteeSeatRemoved.Trigger(seat) + } } diff --git a/pkg/protocol/sybilprotection/sybilprotectionv1/performance/performance.go b/pkg/protocol/sybilprotection/sybilprotectionv1/performance/performance.go index a798ff647..f5f024a56 100644 --- a/pkg/protocol/sybilprotection/sybilprotectionv1/performance/performance.go +++ b/pkg/protocol/sybilprotection/sybilprotectionv1/performance/performance.go @@ -141,6 +141,13 @@ func (t *Tracker) ValidatorCandidates(epoch iotago.EpochIndex) (ds.Set[iotago.Ac } func (t *Tracker) getValidatorCandidates(epoch iotago.EpochIndex) (ds.Set[iotago.AccountID], error) { + candidates := ds.NewSet[iotago.AccountID]() + + // Epoch 0 has no candidates as it's the genesis committee. + if epoch == 0 { + return candidates, nil + } + // we store candidates in the store for the epoch of their activity, but the passed argument points to the target epoch, // so it's necessary to subtract one epoch from the passed value candidateStore, err := t.committeeCandidatesInEpochFunc(epoch - 1) @@ -148,8 +155,6 @@ func (t *Tracker) getValidatorCandidates(epoch iotago.EpochIndex) (ds.Set[iotago return nil, ierrors.Wrapf(err, "error while retrieving candidates for epoch %d", epoch) } - candidates := ds.NewSet[iotago.AccountID]() - var innerErr error err = candidateStore.IterateKeys(kvstore.EmptyPrefix, func(key kvstore.Key) bool { accountID, _, err := iotago.AccountIDFromBytes(key) diff --git a/tools/docker-network/docker-compose.yml b/tools/docker-network/docker-compose.yml index 22d21b2dc..a16297065 100644 --- a/tools/docker-network/docker-compose.yml +++ b/tools/docker-network/docker-compose.yml @@ -20,10 +20,10 @@ services: networks: - iota-core ports: - - "8080:14265/tcp" # REST-API - - "8081:8081/tcp" # Dashboard - - "6081:6061/tcp" # pprof - - "9089:9029/tcp" # INX + - "8050:14265/tcp" # REST-API + - "8051:8081/tcp" # Dashboard + - "6051:6061/tcp" # pprof + - "9059:9029/tcp" # INX volumes: - ./docker-network.snapshot:/app/data/snapshot.bin - ./config.json:/app/config.json:ro @@ -31,10 +31,6 @@ services: ${COMMON_CONFIG} ${MANUALPEERING_CONFIG} --p2p.identityPrivateKey=08735375679f3d8031353e94282ed1d65119e5c288fe56d6639d9184a3f978fee8febfedff11cc376daea0f59c395ae2e9a870a25ac4e36093000fbf4d0e8f18 - --validator.enabled=true - --validator.ignoreBootstrapped=true - --validator.account=0x907c02e9302e0f0571f10f885594e56d8c54ff0708ab7a39bc1b74d396b93b12 - --validator.privateKey=443a988ea61797651217de1f4662d4d6da11fd78e67f94511453bf6576045a05293dc170d9a59474e6d81cfba7f7d924c09b25d7166bcfba606e53114d0a758b --inx.enabled=true --inx.bindAddress=0.0.0.0:9029 @@ -49,10 +45,10 @@ services: networks: - iota-core ports: - - "8070:14265/tcp" # REST-API - - "8071:8081/tcp" # Dashboard - - "6071:6061/tcp" # pprof - - "9029:9029/tcp" # INX + - "8060:14265/tcp" # REST-API + - "8061:8081/tcp" # Dashboard + - "6061:6061/tcp" # pprof + - "9069:9029/tcp" # INX volumes: - ./docker-network.snapshot:/app/data/snapshot.bin - ./config.json:/app/config.json:ro @@ -60,9 +56,6 @@ services: ${COMMON_CONFIG} ${MANUALPEERING_CONFIG} --p2p.identityPrivateKey=ba771419c52132a0dfb2521ed18667813f398da159010a55a0a482af939affb92d3338789ad4a07a7631b91791deb11f82ed5dc612822f24275e9f7a313b691f - --validator.enabled=true - --validator.account=0x375358f92cc94750669598b0aaa55a6ff73310b90710e1fad524c0f911be0fea - --validator.privateKey=3a5d39f8b60367a17fd54dac2a32c172c8e1fd6cf74ce65f1e13edba565f281705c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064 --inx.enabled=true --inx.bindAddress=0.0.0.0:9029 @@ -77,10 +70,10 @@ services: networks: - iota-core ports: - - "8090:14265/tcp" # REST-API - - "8091:8081/tcp" # Dashboard - - "6091:6061/tcp" # pprof - - "9099:9029/tcp" # INX + - "8070:14265/tcp" # REST-API + - "8071:8081/tcp" # Dashboard + - "6071:6061/tcp" # pprof + - "9079:9029/tcp" # INX volumes: - ./docker-network.snapshot:/app/data/snapshot.bin - ./config.json:/app/config.json:ro @@ -88,9 +81,6 @@ services: ${COMMON_CONFIG} ${MANUALPEERING_CONFIG} --p2p.identityPrivateKey=a6261ac049755675ff1437654ca9f83b305055f01ff08c4f039209ef5a4a7d96d06fb61df77a8815209a8f4d204226dee593e50d0ec897ec440a2c1fbde77656 - --validator.enabled=true - --validator.account=0x6aee704f25558e8aa7630fed0121da53074188abc423b3c5810f80be4936eb6e - --validator.privateKey=db39d2fde6301d313b108dc9db1ee724d0f405f6fde966bd776365bc5f4a5fb31e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648 --inx.enabled=true --inx.bindAddress=0.0.0.0:9029 @@ -105,10 +95,10 @@ services: networks: - iota-core ports: - - "8040:14265/tcp" # REST-API - - "8041:8081/tcp" # Dashboard - - "6041:6061/tcp" # pprof - - "9049:9029/tcp" # INX + - "8080:14265/tcp" # REST-API + - "8081:8081/tcp" # Dashboard + - "6081:6061/tcp" # pprof + - "9089:9029/tcp" # INX volumes: - ./docker-network.snapshot:/app/data/snapshot.bin - ./config.json:/app/config.json:ro @@ -130,10 +120,10 @@ services: networks: - iota-core ports: - - "8030:14265/tcp" # REST-API - - "8031:8081/tcp" # Dashboard - - "6031:6061/tcp" # pprof - - "9039:9029/tcp" # INX + - "8090:14265/tcp" # REST-API + - "8091:8081/tcp" # Dashboard + - "6091:6061/tcp" # pprof + - "9099:9029/tcp" # INX volumes: - ./docker-network.snapshot:/app/data/snapshot.bin - ./config.json:/app/config.json:ro @@ -201,8 +191,8 @@ services: networks: - iota-core command: > - --inx.address=node-1-validator:9029 - --restAPI.bindAddress=inx-indexer:9091 + --inx.address=node-1-validator:9019 + --restAPI.bindAddress=inx-indexer:9011 inx-blockissuer: image: iotaledger/inx-blockissuer:1.0-alpha @@ -245,6 +235,55 @@ services: --faucet.bindAddress=inx-faucet:8091 --faucet.rateLimit.enabled=false + inx-validator-1: + image: iotaledger/inx-validator:1.0-alpha + stop_grace_period: 1m + restart: unless-stopped + depends_on: + node-1-validator: + condition: service_started + networks: + - iota-core + environment: + - "VALIDATOR_PRV_KEY=443a988ea61797651217de1f4662d4d6da11fd78e67f94511453bf6576045a05293dc170d9a59474e6d81cfba7f7d924c09b25d7166bcfba606e53114d0a758b" + command: > + --logger.level=debug + --inx.address=node-1-validator:9029 + --validator.ignoreBootstrapped=true + --validator.accountAddress=rms1pzg8cqhfxqhq7pt37y8cs4v5u4kcc48lquy2k73ehsdhf5ukhya3y5rx2w6 + + inx-validator-2: + image: iotaledger/inx-validator:1.0-alpha + stop_grace_period: 1m + restart: unless-stopped + depends_on: + node-2-validator: + condition: service_started + networks: + - iota-core + environment: + - "VALIDATOR_PRV_KEY=3a5d39f8b60367a17fd54dac2a32c172c8e1fd6cf74ce65f1e13edba565f281705c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064" + command: > + --logger.level=debug + --inx.address=node-2-validator:9029 + --validator.accountAddress=rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl + + inx-validator-3: + image: iotaledger/inx-validator:1.0-alpha + stop_grace_period: 1m + restart: unless-stopped + depends_on: + node-3-validator: + condition: service_started + networks: + - iota-core + environment: + - "VALIDATOR_PRV_KEY=db39d2fde6301d313b108dc9db1ee724d0f405f6fde966bd776365bc5f4a5fb31e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648" + command: > + --logger.level=debug + --inx.address=node-3-validator:9029 + --validator.accountAddress=rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt + # Create our own network networks: iota-core: diff --git a/tools/docker-network/run.sh b/tools/docker-network/run.sh index b137a67a4..7ac82d24a 100755 --- a/tools/docker-network/run.sh +++ b/tools/docker-network/run.sh @@ -6,8 +6,8 @@ function join { local IFS="$1"; shift; echo "$*"; } # All parameters can be optional now, just make sure we don't have too many if [[ $# -gt 4 ]] ; then - echo 'Call with ./run [replicas=1|2|3|...] [monitoring=0|1] [feature=0|1]' - exit 0 + echo 'Call with ./run [replicas=1|2|3|...] [monitoring=0|1] [feature=0|1]' + exit 0 fi REPLICAS=${1:-1} @@ -15,12 +15,10 @@ MONITORING=${2:-0} FEATURE=${3:-0} DOCKER_COMPOSE_FILE=docker-compose.yml -if [ $FEATURE -ne 0 ] -then +if [ $FEATURE -ne 0 ]; then DOCKER_COMPOSE_FILE=docker-compose-feature.yml fi - export DOCKER_BUILDKIT=1 export COMPOSE_DOCKER_CLI_BUILD=1 echo "Build iota-core" @@ -29,8 +27,7 @@ echo "Build iota-core" export DOCKER_BUILD_CONTEXT="../../" export DOCKERFILE_PATH="./Dockerfile.dev" -if [[ "$WITH_GO_WORK" -eq 1 ]] -then +if [[ "$WITH_GO_WORK" -eq 1 ]]; then export DOCKER_BUILD_CONTEXT="../../../" export DOCKERFILE_PATH="./iota-core/Dockerfile.dev" fi @@ -39,36 +36,34 @@ fi echo $DOCKER_BUILD_CONTEXT $DOCKERFILE_PATH docker compose -f $DOCKER_COMPOSE_FILE build --build-arg WITH_GO_WORK=${WITH_GO_WORK:-0} --build-arg DOCKER_BUILD_CONTEXT=${DOCKER_BUILD_CONTEXT} --build-arg DOCKERFILE_PATH=${DOCKERFILE_PATH} -docker compose pull inx-indexer inx-blockissuer inx-faucet +docker compose pull inx-indexer inx-blockissuer inx-faucet inx-validator-1 # check exit code of builder -if [ $? -ne 0 ] -then +if [ $? -ne 0 ]; then echo "Building failed. Please fix and try again!" exit 1 fi # create snapshot file echo "Create snapshot" -if [ $FEATURE -ne 0 ] -then - pushd ../genesis-snapshot; go run -tags=rocksdb . --config feature +if [ $FEATURE -ne 0 ]; then + pushd ../genesis-snapshot + go run -tags=rocksdb . --config feature else - pushd ../genesis-snapshot; go run -tags=rocksdb . --config docker --seed 7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih + pushd ../genesis-snapshot + go run -tags=rocksdb . --config docker --seed 7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih fi popd mv ../genesis-snapshot/*.snapshot . chmod o+r *.snapshot - echo "Run iota-core network with ${DOCKER_COMPOSE_FILE}" # IOTA_CORE_PEER_REPLICAS is used in docker-compose.yml to determine how many replicas to create export IOTA_CORE_PEER_REPLICAS=$REPLICAS # Profiles is created to set which docker profiles to run # https://docs.docker.com/compose/profiles/ PROFILES=() -if [ $MONITORING -ne 0 ] -then +if [ $MONITORING -ne 0 ]; then PROFILES+=("monitoring") fi diff --git a/tools/genesis-snapshot/presets/presets.go b/tools/genesis-snapshot/presets/presets.go index 8157c81e2..29babde9f 100644 --- a/tools/genesis-snapshot/presets/presets.go +++ b/tools/genesis-snapshot/presets/presets.go @@ -37,7 +37,15 @@ var Base = []options.Option[snapshotcreator.Options]{ var Docker = []options.Option[snapshotcreator.Options]{ snapshotcreator.WithFilePath("docker-network.snapshot"), snapshotcreator.WithAccounts( - snapshotcreator.AccountDetails{ // node-1-validator + snapshotcreator.AccountDetails{ + /* + node-01-validator + + Ed25519 Public Key: 293dc170d9a59474e6d81cfba7f7d924c09b25d7166bcfba606e53114d0a758b + Ed25519 Address: rms1qzg8cqhfxqhq7pt37y8cs4v5u4kcc48lquy2k73ehsdhf5ukhya3ytgk0ny + Account Address: rms1pzg8cqhfxqhq7pt37y8cs4v5u4kcc48lquy2k73ehsdhf5ukhya3y5rx2w6 + Restricted Address: rms1xqqfqlqzayczurc9w8cslzz4jnjkmrz5lurs32m68x7pkaxnj6unkyspqg8mulpm, Capabilities: mana + */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x293dc170d9a59474e6d81cfba7f7d924c09b25d7166bcfba606e53114d0a758b"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x293dc170d9a59474e6d81cfba7f7d924c09b25d7166bcfba606e53114d0a758b"))), Amount: mock.MinValidatorAccountAmount, @@ -49,7 +57,15 @@ var Docker = []options.Option[snapshotcreator.Options]{ StakedAmount: mock.MinValidatorAccountAmount, Mana: iotago.Mana(mock.MinValidatorAccountAmount), }, - snapshotcreator.AccountDetails{ // node-2-validator + snapshotcreator.AccountDetails{ + /* + node-02-validator + + Ed25519 Public Key: 05c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064 + Ed25519 Address: rms1qqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875flpz2p + Account Address: rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl + Restricted Address: rms1xqqrw56clykvj36sv62e3v9254dxlaenzzuswy8plt2jfs8ezxlql6spqgkulf7u, Capabilities: mana + */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x05c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x05c1de274451db8de8182d64c6ee0dca3ae0c9077e0b4330c976976171d79064"))), Amount: mock.MinValidatorAccountAmount, @@ -61,7 +77,15 @@ var Docker = []options.Option[snapshotcreator.Options]{ StakedAmount: mock.MinValidatorAccountAmount, Mana: iotago.Mana(mock.MinValidatorAccountAmount), }, - snapshotcreator.AccountDetails{ // node-3-validator + snapshotcreator.AccountDetails{ + /* + node-03-validator + + Ed25519 Public Key: 1e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648 + Ed25519 Address: rms1qp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kuvz0a44 + Account Address: rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt + Restricted Address: rms1xqqx4mnsfuj4tr525a3slmgpy8d9xp6p3z4ugganckqslq97fymwkmspqgnzrkjq, Capabilities: mana + */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x1e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x1e4b21eb51dcddf65c20db1065e1f1514658b23a3ddbf48d30c0efc926a9a648"))), Amount: mock.MinValidatorAccountAmount, @@ -77,10 +101,11 @@ var Docker = []options.Option[snapshotcreator.Options]{ /* inx-blockissuer - ed25519 private key: 432c624ca3260f910df35008d5c740593b222f1e196e6cdb8cd1ad080f0d4e33997be92a22b1933f36e26fba5f721756f95811d6b4ae21564197c2bfa4f28270 - ed25519 public key: 997be92a22b1933f36e26fba5f721756f95811d6b4ae21564197c2bfa4f28270 - ed25519 address: edc1c3a42a60a04b69c2fbb6e886414c71c464afbc7d19fb63b36a8065334ada - bech32 address: rms1prkursay9fs2qjmfctamd6yxg9x8r3ry47786x0mvwek4qr9xd9d5c6gkun + Ed25519 Private Key: 432c624ca3260f910df35008d5c740593b222f1e196e6cdb8cd1ad080f0d4e33997be92a22b1933f36e26fba5f721756f95811d6b4ae21564197c2bfa4f28270 + Ed25519 Public Key: 997be92a22b1933f36e26fba5f721756f95811d6b4ae21564197c2bfa4f28270 + Ed25519 Address: rms1qrkursay9fs2qjmfctamd6yxg9x8r3ry47786x0mvwek4qr9xd9d583cnpd + Account Address: rms1prkursay9fs2qjmfctamd6yxg9x8r3ry47786x0mvwek4qr9xd9d5c6gkun + Restricted Address: rms1xqqwmswr5s4xpgztd8p0hdhgseq5cuwyvjhmclgeld3mx65qv5e54kspqgda0nrn, Capabilities: mana */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x997be92a22b1933f36e26fba5f721756f95811d6b4ae21564197c2bfa4f28270"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x997be92a22b1933f36e26fba5f721756f95811d6b4ae21564197c2bfa4f28270"))), @@ -95,12 +120,10 @@ var Docker = []options.Option[snapshotcreator.Options]{ /* inx-faucet - ed25519 private key: de52b9964dda96564e9fab362ab16c2669c715c6a2a853bece8a25fc58c599755b938327ea463e0c323c0fd44f6fc1843ed94daecc6909c6043d06b7152e4737 - ed25519 public key: 5b938327ea463e0c323c0fd44f6fc1843ed94daecc6909c6043d06b7152e4737 - ed25519 address: 2f64f9d179991f50542b01e034fa043b195403875b8677efaf196b41c88803d0 - bech32 address: rms1qqhkf7w30xv375z59vq7qd86qsa3j4qrsadcval04uvkkswg3qpaqf4hga2 - - => restricted address with mana enabled: rms1xqqz7e8e69uej86s2s4srcp5lgzrkx25qwr4hpnha7h3j66pezyq85qpqg55v3ur + Ed25519 Private Key: de52b9964dda96564e9fab362ab16c2669c715c6a2a853bece8a25fc58c599755b938327ea463e0c323c0fd44f6fc1843ed94daecc6909c6043d06b7152e4737 + Ed25519 Public Key: 5b938327ea463e0c323c0fd44f6fc1843ed94daecc6909c6043d06b7152e4737 + Ed25519 Address: rms1qqhkf7w30xv375z59vq7qd86qsa3j4qrsadcval04uvkkswg3qpaqf4hga2 + Restricted Address: rms1xqqz7e8e69uej86s2s4srcp5lgzrkx25qwr4hpnha7h3j66pezyq85qpqg55v3ur, Capabilities: mana */ snapshotcreator.BasicOutputDetails{ Address: lo.Return2(iotago.ParseBech32("rms1xqqz7e8e69uej86s2s4srcp5lgzrkx25qwr4hpnha7h3j66pezyq85qpqg55v3ur")), @@ -125,7 +148,15 @@ var Docker = []options.Option[snapshotcreator.Options]{ var Feature = []options.Option[snapshotcreator.Options]{ snapshotcreator.WithFilePath("docker-network.snapshot"), snapshotcreator.WithAccounts( - snapshotcreator.AccountDetails{ // node-01 + snapshotcreator.AccountDetails{ + /* + node-01-validator + + Ed25519 Public Key: 01fb6b9db5d96240aef00bc950d1c67a6494513f6d7cf784e57b4972b96ab2fe + Ed25519 Address: rms1qqlhggrg2ml9p0q5c4593r2yd3jwgxn20d65ulyw6z9r7xmm78apq4y2mxh + Account Address: rms1pqlhggrg2ml9p0q5c4593r2yd3jwgxn20d65ulyw6z9r7xmm78apq2067mf + Restricted Address: rms1xqqr7apqdpt0u59uznzkskydg3kxfeq6dfah2nnu3mgg50cm00cl5yqpqgrpy62q, Capabilities: mana + */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x01fb6b9db5d96240aef00bc950d1c67a6494513f6d7cf784e57b4972b96ab2fe"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x01fb6b9db5d96240aef00bc950d1c67a6494513f6d7cf784e57b4972b96ab2fe"))), Amount: mock.MinValidatorAccountAmount, @@ -137,7 +168,15 @@ var Feature = []options.Option[snapshotcreator.Options]{ StakedAmount: mock.MinValidatorAccountAmount, Mana: iotago.Mana(mock.MinValidatorAccountAmount), }, - snapshotcreator.AccountDetails{ // node-02 + snapshotcreator.AccountDetails{ + /* + node-02-validator + + Ed25519 Public Key: 83e7f71a440afd48981a8b4684ddae24434b7182ce5c47cfb56ac528525fd4b6 + Ed25519 Address: rms1qzjwamvhjuqtw3dkfwmmj2fgcetcdyt4uxrnjxel4caxfstzz903ypu8xvn + Account Address: rms1pzjwamvhjuqtw3dkfwmmj2fgcetcdyt4uxrnjxel4caxfstzz903y7hhr3d + Restricted Address: rms1xqq2fmhdj7tspd69ke9m0wff9rr90p53whscwwgm87hr5expvgg47yspqgm6whkx, Capabilities: mana + */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x83e7f71a440afd48981a8b4684ddae24434b7182ce5c47cfb56ac528525fd4b6"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x83e7f71a440afd48981a8b4684ddae24434b7182ce5c47cfb56ac528525fd4b6"))), Amount: mock.MinValidatorAccountAmount, @@ -149,7 +188,15 @@ var Feature = []options.Option[snapshotcreator.Options]{ StakedAmount: mock.MinValidatorAccountAmount, Mana: iotago.Mana(mock.MinValidatorAccountAmount), }, - snapshotcreator.AccountDetails{ // node-03 + snapshotcreator.AccountDetails{ + /* + node-03-validator + + Ed25519 Public Key: ac628986b2ef52a1679f2289fcd7b4198476976dea4c30ae34ff04ae52e14805 + Ed25519 Address: rms1qz6kedkxyw9md2cmp0wcdhvsxrn2e7gzuyly76ffymy4dhvtkm58qlkjupg + Account Address: rms1pz6kedkxyw9md2cmp0wcdhvsxrn2e7gzuyly76ffymy4dhvtkm58qqazeuk + Restricted Address: rms1xqqt2m9kcc3chd4trv9ampkajqcwdt8eqtsnunmf9ynvj4ka3wmwsuqpqgvp9zxl, Capabilities: mana + */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0xac628986b2ef52a1679f2289fcd7b4198476976dea4c30ae34ff04ae52e14805"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0xac628986b2ef52a1679f2289fcd7b4198476976dea4c30ae34ff04ae52e14805"))), Amount: mock.MinValidatorAccountAmount, @@ -165,9 +212,10 @@ var Feature = []options.Option[snapshotcreator.Options]{ /* inx-blockissuer - ed25519 public key: 670a1a20ddb02a6cec53ec3196bc7d5bd26df2f5a6ca90b5fffd71364f104b25 - ed25519 address: 3b07e3e84c1276f0b9d35cf218b3763e0cbdadaa7ca38588de2170c31b38e9bb - bech32 address: rms1pqas0clgfsf8du9e6dw0yx9nwclqe0dd4f728pvgmcshpscm8r5mkddrrfc + Ed25519 Public Key: 670a1a20ddb02a6cec53ec3196bc7d5bd26df2f5a6ca90b5fffd71364f104b25 + Ed25519 Address: rms1qqas0clgfsf8du9e6dw0yx9nwclqe0dd4f728pvgmcshpscm8r5mkjxnx5x + Account Address: rms1pqas0clgfsf8du9e6dw0yx9nwclqe0dd4f728pvgmcshpscm8r5mkddrrfc + Restricted Address: rms1xqqrkplrapxpyahsh8f4eusckdmrur9a4k48egu93r0zzuxrrvuwnwcpqgj0nu8t, Capabilities: mana */ AccountID: blake2b.Sum256(lo.PanicOnErr(hexutil.DecodeHex("0x670a1a20ddb02a6cec53ec3196bc7d5bd26df2f5a6ca90b5fffd71364f104b25"))), Address: iotago.Ed25519AddressFromPubKey(lo.PanicOnErr(hexutil.DecodeHex("0x670a1a20ddb02a6cec53ec3196bc7d5bd26df2f5a6ca90b5fffd71364f104b25"))), @@ -182,11 +230,9 @@ var Feature = []options.Option[snapshotcreator.Options]{ /* inx-faucet - ed25519 public key: dcd760a51cfafe901f4ca0745d399af7146028af643e8a339c7bb82fbb1be7f9 - ed25519 address: 48acd764f626523646d5ccf22f807e96d30b7ab0064f370b66fa811985985ec4 - bech32 address: rms1qpy2e4my7cn9ydjx6hx0ytuq06tdxzm6kqry7dctvmagzxv9np0vg9c55n4 - - => restricted address with mana enabled: rms1xqqy3txhvnmzv53kgm2ueu30splfd5ct02cqvnehpdn04qgeskv9a3qpqgrhlhv3 + Ed25519 Public Key: dcd760a51cfafe901f4ca0745d399af7146028af643e8a339c7bb82fbb1be7f9 + Ed25519 Address: rms1qpy2e4my7cn9ydjx6hx0ytuq06tdxzm6kqry7dctvmagzxv9np0vg9c55n4 + Restricted Address: rms1xqqy3txhvnmzv53kgm2ueu30splfd5ct02cqvnehpdn04qgeskv9a3qpqgrhlhv3, Capabilities: mana */ snapshotcreator.BasicOutputDetails{ Address: lo.Return2(iotago.ParseBech32("rms1xqqy3txhvnmzv53kgm2ueu30splfd5ct02cqvnehpdn04qgeskv9a3qpqgrhlhv3")),