diff --git a/client/evilwallet/connector.go b/client/evilwallet/connector.go index 3b849e0906..42fb9be10a 100644 --- a/client/evilwallet/connector.go +++ b/client/evilwallet/connector.go @@ -81,8 +81,6 @@ func (c *WebClients) ServerStatus(cltIdx int) (status *wallet.ServerStatus, err status.ID = response.IdentityID status.Synced = response.TangleTime.Synced status.Version = response.Version - status.ManaDecay = response.ManaDecay - status.DelegationAddress = response.ManaDelegationAddress return status, nil } diff --git a/client/mana.go b/client/mana.go index 5ea78a6ac0..e2d3280bcd 100644 --- a/client/mana.go +++ b/client/mana.go @@ -129,16 +129,6 @@ func (api *GoShimmerAPI) GetNHighestConsensusMana(n int) (*jsonmodels.GetNHighes return res, nil } -// GetPending returns the mana (bm2) that will be pledged by spending the output specified. -func (api *GoShimmerAPI) GetPending(outputID string) (*jsonmodels.PendingResponse, error) { - res := &jsonmodels.PendingResponse{} - if err := api.do(http.MethodGet, routePending, - &jsonmodels.PendingRequest{OutputID: outputID}, res); err != nil { - return nil, err - } - return res, nil -} - // GetPastConsensusManaVector returns the consensus base mana vector of a time in the past. func (api *GoShimmerAPI) GetPastConsensusManaVector(t int64) (*jsonmodels.PastConsensusManaVectorResponse, error) { res := &jsonmodels.PastConsensusManaVectorResponse{} diff --git a/client/wallet/packages/delegateoptions/options.go b/client/wallet/packages/delegateoptions/options.go index 72a76255a9..9d4bcea219 100644 --- a/client/wallet/packages/delegateoptions/options.go +++ b/client/wallet/packages/delegateoptions/options.go @@ -3,91 +3,10 @@ package delegateoptions import ( "time" - "github.com/cockroachdb/errors" - "github.com/iotaledger/goshimmer/client/wallet/packages/address" - "github.com/iotaledger/goshimmer/client/wallet/packages/constants" "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" ) -// DelegateFundsOption is the type for the optional parameters for the DelegateFunds call. -type DelegateFundsOption func(*DelegateFundsOptions) error - -// Destination is an option for the SendFunds call that defines a destination for funds that are supposed to be moved. -func Destination(addr address.Address, balance map[devnetvm.Color]uint64) DelegateFundsOption { - // return an error if the IOTA amount is less - if balance[devnetvm.ColorIOTA] < devnetvm.DustThresholdAliasOutputIOTA { - return optionError(errors.Errorf("the IOTA amount provided in the destination needs to be larger than %d", devnetvm.DustThresholdAliasOutputIOTA)) - } - - // return Option - return func(options *DelegateFundsOptions) error { - // initialize destinations property - if options.Destinations == nil { - options.Destinations = make(map[address.Address]map[devnetvm.Color]uint64) - } - - // initialize address specific destination - if _, addressExists := options.Destinations[addr]; !addressExists { - options.Destinations[addr] = make(map[devnetvm.Color]uint64) - } - - for color, amount := range balance { - // increase amount - options.Destinations[addr][color] += amount - } - return nil - } -} - -// DelegateUntil is an option for the DelegateFunds call that specifies until when the delegation should last. -func DelegateUntil(until time.Time) DelegateFundsOption { - return func(options *DelegateFundsOptions) error { - if until.Before(time.Now()) { - return errors.Errorf("can't delegate funds in the past") - } - if until.After(constants.MaxRepresentableTime) { - return errors.Errorf("delegation is only supported until %s", constants.MaxRepresentableTime) - } - options.DelegateUntil = until - return nil - } -} - -// Remainder is an option for the SendsFunds call that allows us to specify the remainder address that is -// supposed to be used in the corresponding transaction. -func Remainder(addr address.Address) DelegateFundsOption { - return func(options *DelegateFundsOptions) error { - options.RemainderAddress = addr - - return nil - } -} - -// AccessManaPledgeID is an option for SendFunds call that defines the nodeID to pledge access mana to. -func AccessManaPledgeID(nodeID string) DelegateFundsOption { - return func(options *DelegateFundsOptions) error { - options.AccessManaPledgeID = nodeID - return nil - } -} - -// ConsensusManaPledgeID is an option for SendFunds call that defines the nodeID to pledge consensus mana to. -func ConsensusManaPledgeID(nodeID string) DelegateFundsOption { - return func(options *DelegateFundsOptions) error { - options.ConsensusManaPledgeID = nodeID - return nil - } -} - -// WaitForConfirmation defines if the call should wait for confirmation before it returns. -func WaitForConfirmation(wait bool) DelegateFundsOption { - return func(options *DelegateFundsOptions) error { - options.WaitForConfirmation = wait - return nil - } -} - // DelegateFundsOptions is a struct that is used to aggregate the optional parameters provided in the DelegateFunds call. type DelegateFundsOptions struct { Destinations map[address.Address]map[devnetvm.Color]uint64 @@ -113,34 +32,4 @@ func (s *DelegateFundsOptions) RequiredFunds() map[devnetvm.Color]uint64 { } } return requiredFunds -} - -// Build is a utility function that constructs the DelegateFundsOptions. -func Build(options ...DelegateFundsOption) (result *DelegateFundsOptions, err error) { - // create options to collect the arguments provided - result = &DelegateFundsOptions{} - - // apply arguments to our options - for _, option := range options { - if err = option(result); err != nil { - return - } - } - - // sanitize parameters - if len(result.Destinations) == 0 { - err = errors.New("you need to provide at least one Destination for a valid delegation to be issued") - - return - } - - return -} - -// optionError is a utility function that returns a Option that returns the error provided in the -// argument. -func optionError(err error) DelegateFundsOption { - return func(options *DelegateFundsOptions) error { - return err - } -} +} \ No newline at end of file diff --git a/client/wallet/serverstatus.go b/client/wallet/serverstatus.go index 28473f78bc..bc88a8c9b8 100644 --- a/client/wallet/serverstatus.go +++ b/client/wallet/serverstatus.go @@ -5,6 +5,4 @@ type ServerStatus struct { ID string Synced bool Version string - ManaDecay float64 - DelegationAddress string } diff --git a/client/wallet/wallet.go b/client/wallet/wallet.go index 86d85d13fc..ad1dafe35b 100644 --- a/client/wallet/wallet.go +++ b/client/wallet/wallet.go @@ -16,10 +16,8 @@ import ( "github.com/iotaledger/goshimmer/client/wallet/packages/claimconditionaloptions" "github.com/iotaledger/goshimmer/client/wallet/packages/consolidateoptions" "github.com/iotaledger/goshimmer/client/wallet/packages/createnftoptions" - "github.com/iotaledger/goshimmer/client/wallet/packages/delegateoptions" "github.com/iotaledger/goshimmer/client/wallet/packages/deposittonftoptions" "github.com/iotaledger/goshimmer/client/wallet/packages/destroynftoptions" - "github.com/iotaledger/goshimmer/client/wallet/packages/reclaimoptions" "github.com/iotaledger/goshimmer/client/wallet/packages/seed" "github.com/iotaledger/goshimmer/client/wallet/packages/sendoptions" "github.com/iotaledger/goshimmer/client/wallet/packages/sweepnftownednftsoptions" @@ -413,149 +411,6 @@ func (wallet *Wallet) CreateAsset(asset Asset, waitForConfirmation ...bool) (ass // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// -// region DelegateFunds //////////////////////////////////////////////////////////////////////////////////////////////// - -// DelegateFunds delegates funds to a given address by creating a delegated alias output. -func (wallet *Wallet) DelegateFunds(options ...delegateoptions.DelegateFundsOption) (tx *devnetvm.Transaction, delegationIDs []*devnetvm.AliasAddress, err error) { - // build options - delegateOptions, err := delegateoptions.Build(options...) - if err != nil { - return - } - - // how much funds will we need to fund this transfer? - requiredFunds := delegateOptions.RequiredFunds() - // collect that many outputs for funding - consumedOutputs, err := wallet.collectOutputsForFunding(requiredFunds, false) - if err != nil { - if errors.Is(err, ErrTooManyOutputs) { - err = errors.Errorf("consolidate funds and try again: %w", err) - } - return - } - - // determine pledgeIDs - aPledgeID, cPledgeID, err := wallet.derivePledgeIDs(delegateOptions.AccessManaPledgeID, delegateOptions.ConsensusManaPledgeID) - if err != nil { - return - } - - // build inputs from consumed outputs - inputs := wallet.buildInputs(consumedOutputs) - // aggregate all the funds we consume from inputs - totalConsumedFunds := consumedOutputs.TotalFundsInOutputs() - remainderAddress := wallet.chooseRemainderAddress(consumedOutputs, delegateOptions.RemainderAddress) - - unsortedOutputs := devnetvm.Outputs{} - for addr, balanceMap := range delegateOptions.Destinations { - var delegationOutput *devnetvm.AliasOutput - delegationOutput, err = devnetvm.NewAliasOutputMint(balanceMap, addr.Address()) - if err != nil { - return - } - // we are the governance controllers, so we can claim back the delegated funds - delegationOutput.SetGoverningAddress(wallet.ReceiveAddress().Address()) - // is there a delegation timelock? - if !delegateOptions.DelegateUntil.IsZero() { - delegationOutput = delegationOutput.WithDelegationAndTimelock(delegateOptions.DelegateUntil) - } else { - delegationOutput = delegationOutput.WithDelegation() - } - unsortedOutputs = append(unsortedOutputs, delegationOutput) - } - // remainder balance = totalConsumed - required - for color, balance := range requiredFunds { - if totalConsumedFunds[color] < balance { - err = errors.Errorf("delegated funds are greater than consumed funds") - return - } - totalConsumedFunds[color] -= balance - if totalConsumedFunds[color] <= 0 { - delete(totalConsumedFunds, color) - } - } - // only create remainder output if there is a remainder balance - if len(totalConsumedFunds) > 0 { - remainderBalances := devnetvm.NewColoredBalances(totalConsumedFunds) - unsortedOutputs = append(unsortedOutputs, devnetvm.NewSigLockedColoredOutput(remainderBalances, remainderAddress.Address())) - } - - outputs := devnetvm.NewOutputs(unsortedOutputs...) - txEssence := devnetvm.NewTransactionEssence(0, time.Now(), aPledgeID, cPledgeID, inputs, outputs) - outputsByID := consumedOutputs.OutputsByID() - unlockBlocks, inputsAsOutputsInOrder := wallet.buildUnlockBlocks(inputs, outputsByID, txEssence) - tx = devnetvm.NewTransaction(txEssence, unlockBlocks) - - txBytes, err := tx.Bytes() - if err != nil { - return - } - // check syntactical validity by marshaling an unmarshalling - tx = new(devnetvm.Transaction) - err = tx.FromBytes(txBytes) - if err != nil { - return - } - - // check tx validity (balances, unlock blocks) - ok, err := checkBalancesAndUnlocks(inputsAsOutputsInOrder, tx) - if err != nil { - return - } - if !ok { - err = errors.Errorf("created transaction is invalid: %s", tx.String()) - return - } - - // look for the ids of the freshly created delegation aliases that are only available after the outputID is set. - delegationIDs = make([]*devnetvm.AliasAddress, 0) - for _, output := range tx.Essence().Outputs() { - if output.Type() == devnetvm.AliasOutputType { - // Address() for an alias output returns the alias address, the unique ID of the alias - delegationIDs = append(delegationIDs, output.Address().(*devnetvm.AliasAddress)) - } - } - - wallet.markOutputsAndAddressesSpent(consumedOutputs) - - err = wallet.connector.SendTransaction(tx) - if err != nil { - return - } - if delegateOptions.WaitForConfirmation { - err = wallet.WaitForTxConfirmation(tx.ID()) - } - - return -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// region ReclaimDelegatedFunds //////////////////////////////////////////////////////////////////////////////////////// - -// ReclaimDelegatedFunds reclaims delegated funds (alias outputs). -func (wallet *Wallet) ReclaimDelegatedFunds(options ...reclaimoptions.ReclaimFundsOption) (tx *devnetvm.Transaction, err error) { - // build options - reclaimOptions, err := reclaimoptions.Build(options...) - if err != nil { - return - } - if reclaimOptions.ToAddress == nil { - // if no optional address is provided, send to receive address of the wallet - reclaimOptions.ToAddress = wallet.ReceiveAddress().Address() - } - - tx, err = wallet.DestroyNFT( - destroynftoptions.Alias(reclaimOptions.Alias.Base58()), - destroynftoptions.RemainderAddress(reclaimOptions.ToAddress.Base58()), - destroynftoptions.WaitForConfirmation(reclaimOptions.WaitForConfirmation), - ) - - return -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// - // region CreateNFT //////////////////////////////////////////////////////////////////////////////////////////////////// // CreateNFT spends funds from the wallet to create an NFT. diff --git a/client/wallet/webconnector.go b/client/wallet/webconnector.go index f47837bfa2..66b02a64f3 100644 --- a/client/wallet/webconnector.go +++ b/client/wallet/webconnector.go @@ -34,8 +34,6 @@ func (webConnector *WebConnector) ServerStatus() (status ServerStatus, err error status.ID = response.IdentityID status.Synced = response.TangleTime.Synced status.Version = response.Version - status.ManaDecay = response.ManaDecay - status.DelegationAddress = response.ManaDelegationAddress return } diff --git a/deploy/ansible/hosts/feature.yml b/deploy/ansible/hosts/feature.yml index aace21d034..5502ebfa4c 100644 --- a/deploy/ansible/hosts/feature.yml +++ b/deploy/ansible/hosts/feature.yml @@ -42,5 +42,4 @@ goshimmers: logLevel: "debug" debugPorts: true remoteDebugging: true - snapshotResetTime: true spammer: true diff --git a/deploy/ansible/roles/goshimmer-node/templates/docker-compose-analysis-server.yml.j2 b/deploy/ansible/roles/goshimmer-node/templates/docker-compose-analysis-server.yml.j2 index 0904eea16f..4969a4f7e7 100644 --- a/deploy/ansible/roles/goshimmer-node/templates/docker-compose-analysis-server.yml.j2 +++ b/deploy/ansible/roles/goshimmer-node/templates/docker-compose-analysis-server.yml.j2 @@ -29,5 +29,5 @@ services: --metrics.local=false --metrics.global=true --node.enablePlugins=analysisServer,analysisDashboard,prometheus - --node.disablePlugins=activity,analysisClient,chat,consensus,dashboard,faucet,fpc,gossip,firewall,issuer,mana,manarefresher,manualpeering,messageLayer,metrics,networkdelay,portcheck,pow,syncBeaconFollower,webAPIBroadcastDataEndpoint,WebAPIDataEndpoint,WebAPIHealthzEndpoint,WebAPIFaucetEndpoint,webAPIFindTransactionHashesEndpoint,webAPIGetNeighborsEndpoint,webAPIGetTransactionObjectsByHashEndpoint,webAPIGetTransactionTrytesByHashEndpoint,WebAPIInfoEndpoint,WebAPILedgerstateEndpoint,WebAPIMessageEndpoint,WebAPIToolsMessageEndpoint,WebAPIWeightProviderEndpoint,remotelog,remotelogmetrics,DAGsVisualizer + --node.disablePlugins=activity,analysisClient,chat,consensus,dashboard,faucet,fpc,gossip,firewall,issuer,mana,manualpeering,messageLayer,metrics,networkdelay,portcheck,pow,syncBeaconFollower,webAPIBroadcastDataEndpoint,WebAPIDataEndpoint,WebAPIHealthzEndpoint,WebAPIFaucetEndpoint,webAPIFindTransactionHashesEndpoint,webAPIGetNeighborsEndpoint,webAPIGetTransactionObjectsByHashEndpoint,webAPIGetTransactionTrytesByHashEndpoint,WebAPIInfoEndpoint,WebAPILedgerstateEndpoint,WebAPIMessageEndpoint,WebAPIToolsMessageEndpoint,WebAPIWeightProviderEndpoint,remotelog,remotelogmetrics,DAGsVisualizer --logger.level={{ logLevel }} diff --git a/deploy/ansible/roles/goshimmer-node/templates/docker-compose-entrynode.yml.j2 b/deploy/ansible/roles/goshimmer-node/templates/docker-compose-entrynode.yml.j2 index 349134f821..773bf4b578 100644 --- a/deploy/ansible/roles/goshimmer-node/templates/docker-compose-entrynode.yml.j2 +++ b/deploy/ansible/roles/goshimmer-node/templates/docker-compose-entrynode.yml.j2 @@ -26,5 +26,5 @@ services: {% endif %} --autoPeering.entryNodes= --analysis.client.serverAddress= - --node.disablePlugins=activity,analysisClient,chat,consensus,dashboard,faucet,fpc,gossip,firewall,issuer,mana,manarefresher,manualpeering,messageLayer,metrics,networkdelay,portcheck,pow,syncBeaconFollower,webAPIBroadcastDataEndpoint,WebAPIDataEndpoint,WebAPIHealthzEndpoint,WebAPIFaucetEndpoint,webAPIFindTransactionHashesEndpoint,webAPIGetNeighborsEndpoint,webAPIGetTransactionObjectsByHashEndpoint,webAPIGetTransactionTrytesByHashEndpoint,WebAPIInfoEndpoint,WebAPILedgerstateEndpoint,WebAPIMessageEndpoint,WebAPIToolsMessageEndpoint,WebAPIWeightProviderEndpoint,remotelog,remotelogmetrics,DAGsVisualizer + --node.disablePlugins=activity,analysisClient,chat,consensus,dashboard,faucet,fpc,gossip,firewall,issuer,mana,manualpeering,messageLayer,metrics,networkdelay,portcheck,pow,syncBeaconFollower,webAPIBroadcastDataEndpoint,WebAPIDataEndpoint,WebAPIHealthzEndpoint,WebAPIFaucetEndpoint,webAPIFindTransactionHashesEndpoint,webAPIGetNeighborsEndpoint,webAPIGetTransactionObjectsByHashEndpoint,webAPIGetTransactionTrytesByHashEndpoint,WebAPIInfoEndpoint,WebAPILedgerstateEndpoint,WebAPIMessageEndpoint,WebAPIToolsMessageEndpoint,WebAPIWeightProviderEndpoint,remotelog,remotelogmetrics,DAGsVisualizer --logger.level={{ logLevel }} diff --git a/deploy/ansible/roles/goshimmer-node/templates/docker-compose-goshimmer.yml.j2 b/deploy/ansible/roles/goshimmer-node/templates/docker-compose-goshimmer.yml.j2 index 533f40163f..3397a17e5c 100644 --- a/deploy/ansible/roles/goshimmer-node/templates/docker-compose-goshimmer.yml.j2 +++ b/deploy/ansible/roles/goshimmer-node/templates/docker-compose-goshimmer.yml.j2 @@ -46,9 +46,6 @@ services: - PROFILING_BINDADDRESS=0.0.0.0:6061 command: > --skip-config=true - {% if snapshotResetTime|default(false) %} - --mana.snapshotResetTime=true - {% endif %} --autoPeering.entryNodes={{ entryNodePubKey }}@{{ entryNodeHost }}:15626{% if communityEntryNode|default(None) %},{{ communityEntryNode }}{% endif %} {% if networkVersion|default(None) %} --autoPeering.networkVersion={{ networkVersion }} diff --git a/packages/jsonmodels/info.go b/packages/jsonmodels/info.go index 47a55cb8ca..fdc329e1c3 100644 --- a/packages/jsonmodels/info.go +++ b/packages/jsonmodels/info.go @@ -30,10 +30,6 @@ type InfoResponse struct { DisabledPlugins []string `json:"disabledPlugins,omitempty"` // Mana values Mana Mana `json:"mana,omitempty"` - // Mana Delegation Address - ManaDelegationAddress string `json:"manaDelegationAddress,omitempty"` - // ManaDecay is the decay coefficient of bm2. - ManaDecay float64 `json:"mana_decay"` // Scheduler is the scheduler. Scheduler Scheduler `json:"scheduler"` // error of the response diff --git a/packages/jsonmodels/mana.go b/packages/jsonmodels/mana.go index d9e23b4530..09a2014052 100644 --- a/packages/jsonmodels/mana.go +++ b/packages/jsonmodels/mana.go @@ -88,19 +88,6 @@ type PastConsensusManaVectorResponse struct { TimeStamp int64 `json:"timestamp"` } -// PendingRequest is the pending mana request. -type PendingRequest struct { - OutputID string `json:"outputID"` -} - -// PendingResponse is the pending mana response. -type PendingResponse struct { - Mana float64 `json:"mana"` - OutputID string `json:"outputID"` - Error string `json:"error,omitempty"` - Timestamp int64 `json:"timestamp"` -} - // GetPercentileRequest is the request object of mana/percentile. type GetPercentileRequest struct { NodeID string `json:"nodeID"` diff --git a/packages/mana/accessbase.go b/packages/mana/accessbase.go deleted file mode 100644 index 481f3765bf..0000000000 --- a/packages/mana/accessbase.go +++ /dev/null @@ -1,141 +0,0 @@ -package mana - -import ( - "math" - "time" - - "github.com/iotaledger/hive.go/generics/model" -) - -// AccessBaseMana holds information about the access base mana values of a single node. -type AccessBaseMana struct { - model.Mutable[AccessBaseMana, *AccessBaseMana, accessBaseManaModel] `serix:"0"` -} - -type accessBaseManaModel struct { - BaseValue float64 `serix:"0"` - EffectiveValue float64 `serix:"1"` - LastUpdate time.Time `serix:"2"` -} - -// NewAccessBaseMana returns new base access mana vector. -func NewAccessBaseMana(baseMana, effectiveBaseMana float64, lastUpdated time.Time) (newAccessBaseMana *AccessBaseMana) { - return model.NewMutable[AccessBaseMana](&accessBaseManaModel{ - BaseValue: baseMana, - EffectiveValue: effectiveBaseMana, - LastUpdate: lastUpdated, - }) -} - -// EffectiveValue returns effective base mana value. -func (a *AccessBaseMana) EffectiveValue() float64 { - a.RLock() - defer a.RUnlock() - - return a.M.EffectiveValue -} - -// BaseValue returns base mana value. -func (a *AccessBaseMana) BaseValue() float64 { - a.RLock() - defer a.RUnlock() - - return a.M.BaseValue -} - -// LastUpdate returns last update time. -func (a *AccessBaseMana) LastUpdate() time.Time { - a.RLock() - defer a.RUnlock() - - return a.M.LastUpdate -} - -func (a *AccessBaseMana) update(t time.Time) error { - if t.Before(a.LastUpdate()) || t == a.LastUpdate() { - // trying to do a time wise update to the past, that is not allowed - return ErrAlreadyUpdated - } - n := t.Sub(a.LastUpdate()) - a.updateBM2(n) - a.updateEBM2(n) - a.M.LastUpdate = t - return nil -} - -func (a *AccessBaseMana) updateBM2(n time.Duration) { - // zero value doesn't need to be updated - if a.BaseValue() == 0 { - return - } - // close to zero value is considered zero, stop future updates - if a.BaseValue() < DeltaStopUpdate { - a.M.BaseValue = 0 - return - } - a.M.BaseValue *= math.Pow(math.E, -Decay*n.Seconds()) -} - -func (a *AccessBaseMana) updateEBM2(n time.Duration) { - // zero value doesn't need to be updated - if a.BaseValue() == 0 && a.EffectiveValue() == 0 { - return - } - // close to zero value is considered zero, stop future updates - if a.BaseValue() == 0 && a.EffectiveValue() < DeltaStopUpdate { - a.M.EffectiveValue = 0 - return - } - if emaCoeff2 != Decay { - a.M.EffectiveValue = math.Pow(math.E, -emaCoeff2*n.Seconds())*a.EffectiveValue() + - (1-math.Pow(math.E, -(emaCoeff2-Decay)*n.Seconds()))/ - (emaCoeff2-Decay)*emaCoeff2*a.BaseValue() - } else { - a.M.EffectiveValue = math.Pow(math.E, -Decay*n.Seconds())*a.EffectiveValue() + - Decay*n.Seconds()*a.BaseValue() - } -} - -func (a *AccessBaseMana) revoke(float64) error { - panic("access mana cannot be revoked") -} - -func (a *AccessBaseMana) pledge(tx *TxInfo) (pledged float64) { - t := tx.TimeStamp - - if t.After(a.LastUpdate()) { - // regular update - n := t.Sub(a.LastUpdate()) - // first, update BM2 and EBM2 until `t` - a.updateBM2(n) - a.updateEBM2(n) - a.M.LastUpdate = t - // pending mana awarded, need to see how long funds sat - for _, input := range tx.InputInfos { - bm2Add := input.Amount * (1 - math.Pow(math.E, -Decay*(t.Sub(input.TimeStamp).Seconds()))) - a.M.BaseValue += bm2Add - pledged += bm2Add - } - } else { - // past update - n := a.LastUpdate().Sub(t) - // update BM2 at `t` - oldMana2 := a.BaseValue() - for _, input := range tx.InputInfos { - bm2Add := input.Amount * (1 - math.Pow(math.E, -Decay*(t.Sub(input.TimeStamp).Seconds()))) * - math.Pow(math.E, -Decay*n.Seconds()) - a.M.BaseValue += bm2Add - pledged += bm2Add - } - // update EBM2 to `bm.LastUpdate` - if emaCoeff2 != Decay { - a.M.EffectiveValue += (a.BaseValue() - oldMana2) * emaCoeff2 * (math.Pow(math.E, -Decay*n.Seconds()) - - math.Pow(math.E, -emaCoeff2*n.Seconds())) / (emaCoeff2 - Decay) / math.Pow(math.E, -Decay*n.Seconds()) - } else { - a.M.EffectiveValue += (a.BaseValue() - oldMana2) * Decay * n.Seconds() - } - } - return -} - -var _ BaseMana = &AccessBaseMana{} diff --git a/packages/mana/accessbase_test.go b/packages/mana/accessbase_test.go deleted file mode 100644 index 0080ea57bc..0000000000 --- a/packages/mana/accessbase_test.go +++ /dev/null @@ -1,296 +0,0 @@ -package mana - -import ( - "math" - "testing" - "time" - - "github.com/iotaledger/hive.go/identity" - "github.com/stretchr/testify/assert" -) - -var delta = 0.001 - -func TestUpdateBM2(t *testing.T) { - t.Run("CASE: Zero values", func(t *testing.T) { - bm := AccessBaseMana{} - bm.Init() - // 0 initial values, timely update should not change anything - bm.updateBM2(time.Hour) - assert.Equal(t, 0.0, bm.BaseValue()) - }) - - t.Run("CASE: Batch update", func(t *testing.T) { - bm := AccessBaseMana{} - bm.Init() - // pledge BM2 at t = o - bm.M.BaseValue = 1.0 - bm.updateBM2(time.Hour * 6) - assert.InDelta(t, 0.5, bm.BaseValue(), delta) - }) - - t.Run("CASE: Incremental update", func(t *testing.T) { - bm := AccessBaseMana{} - bm.Init() - - // pledge BM2 at t = o - bm.M.BaseValue = 1.0 - // with emaCoeff1 = 0.00003209, half value should be reached within 6 hours - for i := 0; i < 6; i++ { - bm.updateBM2(time.Hour) - } - assert.InDelta(t, 0.5, bm.BaseValue(), delta) - }) -} - -func TestUpdateEBM2CoeffEqual(t *testing.T) { - t.Run("CASE: Zero values", func(t *testing.T) { - bm := AccessBaseMana{} - bm.Init() - - // 0 initial values, timely update should not change anything - bm.updateEBM2(time.Hour) - assert.Equal(t, 0.0, bm.M.EffectiveValue) - }) - - t.Run("CASE: Batch and incremental update", func(t *testing.T) { - bmBatch := AccessBaseMana{} - bmBatch.Init() - - // first, let's calculate once on a 6 hour span - // pledge BM2 at t = o - bmBatch.M.BaseValue = 1.0 - // updateEBM2 relies on an update baseMana2 value - bmBatch.updateBM2(time.Hour * 6) - bmBatch.updateEBM2(time.Hour * 6) - - bmInc := AccessBaseMana{} - bmInc.Init() - - // second, let's calculate the same but every hour - // pledge BM2 at t = o - bmInc.M.BaseValue = 1.0 - // with emaCoeff1 = 0.00003209, half value should be reached within 6 hours - for i := 0; i < 6; i++ { - // updateEBM2 relies on an update baseMana2 value - bmInc.updateBM2(time.Hour) - bmInc.updateEBM2(time.Hour) - } - - // compare results of the two calculations - assert.Equal(t, true, math.Abs(bmBatch.M.EffectiveValue-bmInc.M.EffectiveValue) < delta) - }) - - t.Run("CASE: Large durations BM2", func(t *testing.T) { - bmBatch := AccessBaseMana{} - bmBatch.Init() - - // first, let's calculate once on a 6 hour span - // pledge BM2 at t = o - bmBatch.M.BaseValue = 1.0 - // updateEBM2 relies on an update baseMana2 value - minTime := time.Unix(-2208988800, 0) // Jan 1, 1900 - maxTime := minTime.Add(1<<63 - 1) - - bmBatch.updateBM2(maxTime.Sub(minTime)) - - assert.False(t, math.IsNaN(bmBatch.M.BaseValue)) - assert.False(t, math.IsInf(bmBatch.M.BaseValue, 0)) - assert.Equal(t, 0.0, bmBatch.M.BaseValue) - }) - - t.Run("CASE: Large durations EBM2 Decay==emaCoeff2", func(t *testing.T) { - bmBatch := AccessBaseMana{} - bmBatch.Init() - - // pledge BM2 at t = o - bmBatch.M.BaseValue = 1.0 - bmBatch.M.EffectiveValue = 1.0 - - // updateEBM2 relies on an update baseMana2 value - minTime := time.Unix(-2208988800, 0) // Jan 1, 1900 - maxTime := minTime.Add(1<<63 - 1) - - bmBatch.updateBM2(maxTime.Sub(minTime)) - bmBatch.updateEBM2(maxTime.Sub(minTime)) - assert.False(t, math.IsNaN(bmBatch.M.BaseValue)) - assert.False(t, math.IsNaN(bmBatch.M.EffectiveValue)) - assert.False(t, math.IsInf(bmBatch.M.BaseValue, 0)) - assert.False(t, math.IsInf(bmBatch.M.EffectiveValue, 0)) - assert.Equal(t, 0.0, bmBatch.M.BaseValue) - assert.Equal(t, 0.0, bmBatch.M.EffectiveValue) - }) - t.Run("CASE: Large durations EBM2 Decay!=emaCoeff2", func(t *testing.T) { - bmBatch := AccessBaseMana{} - bmBatch.Init() - - SetCoefficients(0.00003209, 0.0057762265, 0.00003209) - // pledge BM2 at t = o - bmBatch.M.BaseValue = 1.0 - bmBatch.M.EffectiveValue = 1.0 - - // updateEBM2 relies on an update baseMana2 value - minTime := time.Unix(-2208988800, 0) // Jan 1, 1900 - maxTime := minTime.Add(1<<63 - 1) - - bmBatch.updateBM2(maxTime.Sub(minTime)) - bmBatch.updateEBM2(maxTime.Sub(minTime)) - - assert.False(t, math.IsNaN(bmBatch.M.BaseValue)) - assert.False(t, math.IsNaN(bmBatch.M.EffectiveValue)) - assert.False(t, math.IsInf(bmBatch.M.BaseValue, 0)) - assert.False(t, math.IsInf(bmBatch.M.EffectiveValue, 0)) - assert.Equal(t, 0.0, bmBatch.BaseValue()) - assert.Equal(t, 0.0, bmBatch.EffectiveValue()) - // re-set the default values so that other tests pass - SetCoefficients(0.00003209, 0.00003209, 0.00003209) - }) -} - -func TestUpdateTimeInPast_Access(t *testing.T) { - baseTime := time.Now() - bm := NewAccessBaseMana(1.0, 0.0, baseTime) - pastTime := baseTime.Add(time.Hour * -1) - err := bm.update(pastTime) - assert.Error(t, err) - assert.Equal(t, ErrAlreadyUpdated, err) -} - -func TestUpdate_Access(t *testing.T) { - baseTime := time.Now() - bm := NewAccessBaseMana(1.0, 0.0, baseTime) - - updateTime := baseTime.Add(time.Hour * 6) - - err := bm.update(updateTime) - assert.NoError(t, err) - // values are only valid for default coefficients of 0.00003209 and t = 6 hours - assert.InDelta(t, 0.5, bm.BaseValue(), delta) - assert.InDelta(t, 0.346573, bm.EffectiveValue(), delta) - assert.Equal(t, updateTime, bm.LastUpdate()) -} - -func TestRevoke_Access(t *testing.T) { - baseTime := time.Now() - bm := NewAccessBaseMana(1.0, 0.0, baseTime) - - assert.Panics(t, func() { - _ = bm.revoke(1.0) - }) -} - -func TestPledgeRegularOldFunds_Access(t *testing.T) { - baseTime := time.Now() - bm := NewAccessBaseMana(1.0, 0.0, baseTime) - - // transaction pledges mana at t=6 hours with 3 inputs. - txInfo := &TxInfo{ - TimeStamp: baseTime.Add(time.Hour * 6), - TotalBalance: 10.0, - PledgeID: map[Type]identity.ID{}, // don't care - InputInfos: []InputInfo{ - { - // funds have been sitting here for couple days... - TimeStamp: baseTime.Add(time.Hour * -200), - Amount: 5.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - { - // funds have been sitting here for couple days... - TimeStamp: baseTime.Add(time.Hour * -200), - Amount: 3.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - { - // funds have been sitting here for couple days... - TimeStamp: baseTime.Add(time.Hour * -200), - Amount: 2.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - }, - } - - bm2Pledged := bm.pledge(txInfo) - - assert.InDelta(t, 10.0, bm2Pledged, delta) - // half of the original BM2 degraded away in 6 hours - assert.InDelta(t, 10.5, bm.BaseValue(), delta) -} - -func TestPledgeRegularHalfOldFunds_Access(t *testing.T) { - baseTime := time.Now() - bm := NewAccessBaseMana(1.0, 0.0, baseTime) - - // transaction pledges mana at t=6 hours with 3 inputs. - txInfo := &TxInfo{ - TimeStamp: baseTime.Add(time.Hour * 6), - TotalBalance: 10.0, - PledgeID: map[Type]identity.ID{}, // don't care - InputInfos: []InputInfo{ - { - // funds have been sitting here for 6 hours - TimeStamp: baseTime, - Amount: 5.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - { - // funds have been sitting here for 6 hours - TimeStamp: baseTime, - Amount: 3.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - { - // funds have been sitting here for 6 hours - TimeStamp: baseTime, - Amount: 2.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - }, - } - - bm2Pledged := bm.pledge(txInfo) - - assert.InDelta(t, 5.0, bm2Pledged, delta) - // half of the original BM2 degraded away in 6 hours - assert.InDelta(t, 5.5, bm.BaseValue(), delta) -} - -func TestPledgePastOldFunds_Access(t *testing.T) { - baseTime := time.Now() - bm := NewAccessBaseMana(0, 0.0, baseTime.Add(time.Hour*6)) - - // transaction pledges mana at t=0 hours with 3 inputs. - txInfo := &TxInfo{ - TimeStamp: baseTime, - TotalBalance: 10.0, - PledgeID: map[Type]identity.ID{}, // don't care - InputInfos: []InputInfo{ - { - // funds have been sitting here for couple days... - TimeStamp: baseTime.Add(time.Hour * -200), - Amount: 5.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - { - // funds have been sitting here for couple days... - TimeStamp: baseTime.Add(time.Hour * -200), - Amount: 3.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - { - // funds have been sitting here for couple days... - TimeStamp: baseTime.Add(time.Hour * -200), - Amount: 2.0, - PledgeID: map[Type]identity.ID{}, // don't care - }, - }, - } - - bm2Pledged := bm.pledge(txInfo) - - // pledged at t=0, half of input amount is added to bm2 - assert.InDelta(t, 5.0, bm2Pledged, delta) - // half of the original BM2 degraded away in 6 hours - // valid EBM2 at t=6 hours, after pledging 10 BM2 at t=0 - assert.InDelta(t, 3.465731, bm.EffectiveValue(), delta) -} diff --git a/packages/mana/accessbasevector.go b/packages/mana/accessbasevector.go deleted file mode 100644 index 7df6f63593..0000000000 --- a/packages/mana/accessbasevector.go +++ /dev/null @@ -1,328 +0,0 @@ -package mana - -import ( - "sort" - "time" - - "github.com/cockroachdb/errors" - "github.com/iotaledger/hive.go/generics/model" - "github.com/iotaledger/hive.go/identity" - - "github.com/iotaledger/goshimmer/packages/tangle" -) - -// AccessBaseManaVector represents a base mana vector. -type AccessBaseManaVector struct { - model.Mutable[AccessBaseManaVector, *AccessBaseManaVector, accessBaseManaVectorModel] `serix:"0"` -} - -type accessBaseManaVectorModel struct { - Vector map[identity.ID]*AccessBaseMana `serix:"0"` -} - -// Vector returns the AccessBaseMana vector. -func (a *AccessBaseManaVector) Vector() map[identity.ID]*AccessBaseMana { - return a.M.Vector -} - -// Type returns the type of this mana vector. -func (a *AccessBaseManaVector) Type() Type { - return AccessMana -} - -// Size returns the size of this mana vector. -func (a *AccessBaseManaVector) Size() int { - a.RLock() - defer a.RUnlock() - return len(a.M.Vector) -} - -// Has returns if the given node has mana defined in the vector. -func (a *AccessBaseManaVector) Has(nodeID identity.ID) bool { - a.RLock() - defer a.RUnlock() - _, exists := a.M.Vector[nodeID] - return exists -} - -// LoadSnapshot loads the initial mana state into the base mana vector. -func (a *AccessBaseManaVector) LoadSnapshot(snapshot map[identity.ID]*SnapshotNode) { - a.Lock() - defer a.Unlock() - - // pledging aMana to nodes present in the snapshot as if all was pledged at Timestamp - for nodeID, record := range snapshot { - a.M.Vector[nodeID] = NewAccessBaseMana(record.AccessMana.Value, record.AccessMana.Value, record.AccessMana.Timestamp) - - // trigger events - Events.Pledged.Trigger(&PledgedEvent{ - NodeID: nodeID, - Amount: record.AccessMana.Value, - Time: record.AccessMana.Timestamp, - ManaType: a.Type(), - }) - } -} - -// Book books mana for a transaction. -func (a *AccessBaseManaVector) Book(txInfo *TxInfo) { - var pledgeEvent *PledgedEvent - var updateEvent *UpdatedEvent - func() { - a.Lock() - defer a.Unlock() - pledgeNodeID := txInfo.PledgeID[a.Type()] - if _, exist := a.M.Vector[pledgeNodeID]; !exist { - // first time we see this node - a.M.Vector[pledgeNodeID] = NewAccessBaseMana(0, 0, time.Time{}) - } - // save it for proper event trigger - oldMana := *a.M.Vector[pledgeNodeID] - // actually pledge and update - pledged := a.M.Vector[pledgeNodeID].pledge(txInfo) - pledgeEvent = &PledgedEvent{ - NodeID: pledgeNodeID, - Amount: pledged, - Time: txInfo.TimeStamp, - ManaType: a.Type(), - TransactionID: txInfo.TransactionID, - } - updateEvent = &UpdatedEvent{ - NodeID: pledgeNodeID, - OldMana: &oldMana, - NewMana: a.M.Vector[pledgeNodeID], - ManaType: a.Type(), - } - }() - // trigger events - Events.Pledged.Trigger(pledgeEvent) - Events.Updated.Trigger(updateEvent) -} - -// Update updates the mana entries for a particular node wrt time. -func (a *AccessBaseManaVector) Update(nodeID identity.ID, t time.Time) error { - a.Lock() - defer a.Unlock() - return a.update(nodeID, t) -} - -// UpdateAll updates all entries in the base mana vector wrt to `t`. -func (a *AccessBaseManaVector) UpdateAll(t time.Time) error { - a.Lock() - defer a.Unlock() - for nodeID := range a.M.Vector { - if err := a.update(nodeID, t); err != nil { - return err - } - } - return nil -} - -// GetMana returns Effective Base Mana 2. -func (a *AccessBaseManaVector) GetMana(nodeID identity.ID, optionalUpdateTime ...time.Time) (float64, time.Time, error) { - a.Lock() - defer a.Unlock() - return a.getMana(nodeID, optionalUpdateTime...) -} - -// GetManaMap returns mana perception of the node.. -func (a *AccessBaseManaVector) GetManaMap(optionalUpdateTime ...time.Time) (res NodeMap, t time.Time, err error) { - a.Lock() - defer a.Unlock() - t = time.Now() - if len(optionalUpdateTime) > 0 { - t = optionalUpdateTime[0] - } - res = make(map[identity.ID]float64) - for ID := range a.M.Vector { - var mana float64 - mana, _, err = a.getMana(ID, t) - if err != nil { - return - } - res[ID] = mana - } - return -} - -// GetHighestManaNodes returns the n highest mana nodes in descending order. -// It also updates the mana values for each node. -// If n is zero, it returns all nodes. -func (a *AccessBaseManaVector) GetHighestManaNodes(n uint) (res []Node, t time.Time, err error) { - err = func() error { - // don't lock the vector after this func returns - a.Lock() - defer a.Unlock() - t = time.Now() - for ID := range a.M.Vector { - var mana float64 - mana, _, err = a.getMana(ID, t) - if err != nil { - return err - } - res = append(res, Node{ - ID: ID, - Mana: mana, - }) - } - return nil - }() - if err != nil { - return nil, t, err - } - - sort.Slice(res, func(i, j int) bool { - return res[i].Mana > res[j].Mana - }) - - if n == 0 || int(n) >= len(res) { - return - } - res = res[:n] - return -} - -// GetHighestManaNodesFraction returns the highest mana that own 'p' percent of total mana. -// It also updates the mana values for each node. -// If p is zero or greater than one, it returns all nodes. -func (a *AccessBaseManaVector) GetHighestManaNodesFraction(p float64) (res []Node, t time.Time, err error) { - totalMana := 0.0 - err = func() error { - // don't lock the vector after this func returns - a.Lock() - defer a.Unlock() - t = time.Now() - for ID := range a.M.Vector { - var mana float64 - mana, _, err = a.getMana(ID, t) - if err != nil { - return err - } - res = append(res, Node{ - ID: ID, - Mana: mana, - }) - totalMana += mana - } - return nil - }() - if err != nil { - return nil, t, err - } - sort.Slice(res, func(i, j int) bool { - return res[i].Mana > res[j].Mana - }) - - // how much mana is p percent of total mana - manaThreshold := p * totalMana - // include nodes as long as their counted mana is less than the threshold - manaCounted := 0.0 - var n uint - for n = 0; int(n) < len(res) && manaCounted < manaThreshold; n++ { - manaCounted += res[n].Mana - } - - if n == 0 || int(n) >= len(res) { - return - } - res = res[:n] - return res, t, err -} - -// SetMana sets the base mana for a node. -func (a *AccessBaseManaVector) SetMana(nodeID identity.ID, bm BaseMana) { - a.Lock() - defer a.Unlock() - a.M.Vector[nodeID] = bm.(*AccessBaseMana) -} - -// ForEach iterates over the vector and calls the provided callback. -func (a *AccessBaseManaVector) ForEach(callback func(ID identity.ID, bm BaseMana) bool) { - // lock to be on the safe side, although callback might just read - a.Lock() - defer a.Unlock() - for nodeID, baseMana := range a.M.Vector { - if !callback(nodeID, baseMana) { - return - } - } -} - -// ToPersistables converts the AccessBaseManaVector to a list of persistable mana objects. -func (a *AccessBaseManaVector) ToPersistables() []*PersistableBaseMana { - a.RLock() - defer a.RUnlock() - var result []*PersistableBaseMana - for nodeID, bm := range a.M.Vector { - pbm := NewPersistableBaseMana(nodeID, a.Type(), []float64{bm.EffectiveValue()}, []float64{bm.EffectiveValue()}, bm.LastUpdate()) - result = append(result, pbm) - } - return result -} - -// FromPersistable fills the AccessBaseManaVector from persistable mana objects. -func (a *AccessBaseManaVector) FromPersistable(p *PersistableBaseMana) (err error) { - if p.ManaType() != AccessMana { - err = errors.Errorf("persistable mana object has type %s instead of %s", p.ManaType().String(), AccessMana.String()) - return - } - if len(p.BaseValues()) != 1 { - err = errors.Errorf("persistable mana object has %d base values instead of 1", len(p.BaseValues())) - return - } - if len(p.EffectiveValues()) != 1 { - err = errors.Errorf("persistable mana object has %d effective values instead of 1", len(p.EffectiveValues())) - return - } - a.Lock() - defer a.Unlock() - a.M.Vector[p.NodeID()] = NewAccessBaseMana(p.BaseValues()[0], p.EffectiveValues()[0], p.LastUpdated()) - return -} - -// RemoveZeroNodes removes the zero mana nodes from the vector. -func (a *AccessBaseManaVector) RemoveZeroNodes() { - a.Lock() - defer a.Unlock() - for nodeID, baseMana := range a.M.Vector { - if baseMana.EffectiveValue() < MinEffectiveMana && baseMana.EffectiveValue() < MinBaseMana { - delete(a.M.Vector, nodeID) - } - } -} - -var _ BaseManaVector = &AccessBaseManaVector{} - -// // Region Internal methods //// - -// update updates the mana entries for a particular node wrt time. Not concurrency safe. -func (a *AccessBaseManaVector) update(nodeID identity.ID, t time.Time) error { - if _, exist := a.M.Vector[nodeID]; !exist { - return ErrNodeNotFoundInBaseManaVector - } - oldMana := *a.M.Vector[nodeID] - if err := a.M.Vector[nodeID].update(t); err != nil { - return err - } - Events.Updated.Trigger(&UpdatedEvent{nodeID, &oldMana, a.M.Vector[nodeID], a.Type()}) - return nil -} - -// getMana returns the current effective mana value. Not concurrency safe. -func (a *AccessBaseManaVector) getMana(nodeID identity.ID, optionalUpdateTime ...time.Time) (float64, time.Time, error) { - t := time.Now() - if _, exist := a.M.Vector[nodeID]; !exist { - return 0, t, nil - } - if len(optionalUpdateTime) > 0 { - t = optionalUpdateTime[0] - } - _ = a.update(nodeID, t) - - baseMana := a.M.Vector[nodeID] - effectiveValue := baseMana.EffectiveValue() - if effectiveValue < tangle.MinMana { - effectiveValue = 0 - } - return effectiveValue, t, nil -} diff --git a/packages/mana/accessbasevector_test.go b/packages/mana/accessbasevector_test.go deleted file mode 100644 index 6e65cdbe97..0000000000 --- a/packages/mana/accessbasevector_test.go +++ /dev/null @@ -1,661 +0,0 @@ -package mana - -import ( - "testing" - "time" - - "github.com/iotaledger/hive.go/generics/event" - "github.com/iotaledger/hive.go/identity" - "github.com/stretchr/testify/assert" - - "github.com/iotaledger/goshimmer/packages/ledger/utxo" -) - -var ( - baseTime = time.Now() - inputTime = baseTime.Add(time.Hour * -200) - txTime = baseTime.Add(time.Hour * 6) - txPledgeID = randNodeID() - inputPledgeID1 = randNodeID() - inputPledgeID2 = randNodeID() - inputPledgeID3 = randNodeID() - beforeBookingAmount = map[identity.ID]float64{ - txPledgeID: 0, - inputPledgeID1: 5.0, - inputPledgeID2: 3.0, - inputPledgeID3: 2.0, - } - afterBookingAmount = map[identity.ID]float64{ - txPledgeID: 10.0, - inputPledgeID1: 0, - inputPledgeID2: 0, - inputPledgeID3: 0, - } - txInfo = &TxInfo{ - TimeStamp: txTime, - TransactionID: randomTxID(), - TotalBalance: 10.0, - PledgeID: map[Type]identity.ID{ - AccessMana: txPledgeID, - ConsensusMana: txPledgeID, - }, - InputInfos: []InputInfo{ - { - // funds have been sitting here for couple days... - TimeStamp: inputTime, - Amount: beforeBookingAmount[inputPledgeID1], - PledgeID: map[Type]identity.ID{ - AccessMana: inputPledgeID1, - ConsensusMana: inputPledgeID1, - }, - InputID: utxo.NewOutputID(randomTxID(), 0), - }, - { - // funds have been sitting here for couple days... - TimeStamp: inputTime, - Amount: beforeBookingAmount[inputPledgeID2], - PledgeID: map[Type]identity.ID{ - AccessMana: inputPledgeID2, - ConsensusMana: inputPledgeID2, - }, - InputID: utxo.NewOutputID(randomTxID(), 0), - }, - { - // funds have been sitting here for couple days... - TimeStamp: inputTime, - Amount: beforeBookingAmount[inputPledgeID3], - PledgeID: map[Type]identity.ID{ - AccessMana: inputPledgeID3, - ConsensusMana: inputPledgeID3, - }, - InputID: utxo.NewOutputID(randomTxID(), 0), - }, - }, - } -) - -func randNodeID() identity.ID { - return identity.GenerateIdentity().ID() -} - -func TestNewBaseManaVector_Access(t *testing.T) { - bmvAccess, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - assert.Equal(t, AccessMana, bmvAccess.Type()) - assert.Equal(t, map[identity.ID]*AccessBaseMana{}, bmvAccess.(*AccessBaseManaVector).M.Vector) -} - -func TestAccessBaseManaVector_Type(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - vectorType := bmv.Type() - assert.Equal(t, AccessMana, vectorType) -} - -func TestAccessBaseManaVector_Size(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - assert.Equal(t, 0, bmv.Size()) - - for i := 0; i < 10; i++ { - bmv.SetMana(randNodeID(), NewAccessBaseMana(float64(i), float64(i), baseTime)) - } - assert.Equal(t, 10, bmv.Size()) -} - -func TestAccessBaseManaVector_Has(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - randID := randNodeID() - - has := bmv.Has(randID) - assert.False(t, has) - - bmv.SetMana(randID, NewAccessBaseMana(0, 0, time.Time{})) - has = bmv.Has(randID) - assert.True(t, has) -} - -func TestAccessBaseManaVector_Book(t *testing.T) { - // hold information about which events triggered - var ( - updateEvents []*UpdatedEvent - revokeEvents []*RevokedEvent - pledgeEvents []*PledgedEvent - ) - - // when an event triggers, add it to the log - Events.Updated.Hook(event.NewClosure(func(ev *UpdatedEvent) { - updateEvents = append(updateEvents, ev) - })) - Events.Revoked.Hook(event.NewClosure(func(ev *RevokedEvent) { - revokeEvents = append(revokeEvents, ev) - })) - Events.Pledged.Hook(event.NewClosure(func(ev *PledgedEvent) { - pledgeEvents = append(pledgeEvents, ev) - })) - - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - // init vector to inputTime with pledged beforeBookingAmount - bmv.SetMana(inputPledgeID1, NewAccessBaseMana(beforeBookingAmount[inputPledgeID1], 0.0, inputTime)) - bmv.SetMana(inputPledgeID2, NewAccessBaseMana(beforeBookingAmount[inputPledgeID2], 0.0, inputTime)) - bmv.SetMana(inputPledgeID3, NewAccessBaseMana(beforeBookingAmount[inputPledgeID3], 0.0, inputTime)) - - // update to txTime - 6 hours. Effective base manas should converge to their asymptote. - err = bmv.UpdateAll(baseTime) - assert.NoError(t, err) - updatedNodeIds := map[identity.ID]interface{}{ - inputPledgeID1: 0, - inputPledgeID2: 0, - inputPledgeID3: 0, - } - for _, ev := range updateEvents { - // has the right type - assert.Equal(t, AccessMana, ev.ManaType) - // has the right update time - assert.Equal(t, baseTime, ev.NewMana.LastUpdate()) - // base mana values are expected - assert.InDelta(t, 0, ev.NewMana.BaseValue(), delta) - assert.InDelta(t, 0, ev.NewMana.EffectiveValue(), delta) - // update triggered for expected nodes - assert.Contains(t, updatedNodeIds, ev.NodeID) - // remove this one from the list of expected to make sure it was only called once - delete(updatedNodeIds, ev.NodeID) - } - assert.Empty(t, updatedNodeIds) - // check the same for the content of the vector - bmv.ForEach(func(ID identity.ID, bm BaseMana) bool { - // has the right update time - assert.Equal(t, baseTime, bm.LastUpdate()) - // base mana values are expected - assert.InDelta(t, 0, bm.BaseValue(), delta) - assert.InDelta(t, 0, bm.EffectiveValue(), delta) - return true - }) - // update event triggered 3 times for the 3 nodes - assert.Equal(t, 3, len(updateEvents)) - assert.Equal(t, 0, len(pledgeEvents)) - assert.Equal(t, 0, len(revokeEvents)) - // drop all recorded updatedEvents - updateEvents = []*UpdatedEvent{} - - // book mana with txInfo at txTime (baseTime + 6 hours) - bmv.Book(txInfo) - - // expected nodeIDs to be called with each event - updatedNodeIds = map[identity.ID]interface{}{ - txPledgeID: 0, - } - pledgedNodeIds := map[identity.ID]interface{}{ - txPledgeID: 0, - } - revokedNodeIds := map[identity.ID]interface{}{} - - // update triggered and once for the pledged - assert.Equal(t, 1, len(updateEvents)) - assert.Equal(t, 1, len(pledgeEvents)) - assert.Equal(t, 0, len(revokeEvents)) - - for _, ev := range updateEvents { - // has the right type - assert.Equal(t, AccessMana, ev.ManaType) - // has the right update time - assert.Equal(t, txTime, ev.NewMana.LastUpdate()) - // base mana values are expected - assert.InDelta(t, afterBookingAmount[ev.NodeID], ev.NewMana.BaseValue(), delta) - assert.InDelta(t, 0, ev.NewMana.EffectiveValue(), delta) - assert.Contains(t, updatedNodeIds, ev.NodeID) - delete(updatedNodeIds, ev.NodeID) - } - assert.Empty(t, updatedNodeIds) - for _, ev := range pledgeEvents { - assert.InDelta(t, afterBookingAmount[ev.NodeID], ev.Amount, delta) - assert.Equal(t, txTime, ev.Time) - assert.Equal(t, txInfo.TransactionID, ev.TransactionID) - assert.Equal(t, AccessMana, ev.ManaType) - assert.Contains(t, pledgedNodeIds, ev.NodeID) - delete(pledgedNodeIds, ev.NodeID) - } - assert.Empty(t, pledgedNodeIds) - for _, ev := range revokeEvents { - assert.Equal(t, beforeBookingAmount[ev.NodeID], ev.Amount) - assert.Equal(t, txTime, ev.Time) - assert.Equal(t, txInfo.TransactionID, ev.TransactionID) - assert.Equal(t, AccessMana, ev.ManaType) - assert.Contains(t, revokedNodeIds, ev.NodeID) - delete(revokedNodeIds, ev.NodeID) - } - assert.Empty(t, revokedNodeIds) - - // drop all recorded updatedEvents - updateEvents = []*UpdatedEvent{} - // expected nodeIDs to be called with each event - updatedNodeIds = map[identity.ID]interface{}{ - txPledgeID: 0, - inputPledgeID1: 0, - inputPledgeID2: 0, - inputPledgeID3: 0, - } - - updateTime := txTime.Add(time.Hour * 6) - err = bmv.UpdateAll(updateTime) - assert.NoError(t, err) - - for _, ev := range updateEvents { - // has the right update time - assert.Equal(t, updateTime, ev.NewMana.LastUpdate()) - // base mana values are expected - if ev.NodeID == txPledgeID { - assert.InDelta(t, afterBookingAmount[ev.NodeID]/2, ev.NewMana.BaseValue(), delta) - assert.InDelta(t, 3.465731, ev.NewMana.EffectiveValue(), delta) - } else { - assert.InDelta(t, 1.0, 1+ev.NewMana.BaseValue(), delta) - assert.InDelta(t, 1.0, 1+ev.NewMana.EffectiveValue(), delta) - } - assert.Contains(t, updatedNodeIds, ev.NodeID) - delete(updatedNodeIds, ev.NodeID) - } - assert.Empty(t, updatedNodeIds) - - // check the same for the content of the vector - bmv.ForEach(func(ID identity.ID, bm BaseMana) bool { - // has the right update time - assert.Equal(t, updateTime, bm.LastUpdate()) - // base mana values are expected - if ID == txPledgeID { - assert.InDelta(t, afterBookingAmount[ID]/2, bm.BaseValue(), delta) - assert.InDelta(t, 3.465731, bm.EffectiveValue(), delta) - } else { - assert.InDelta(t, 1.0, 1+bm.BaseValue(), delta) - assert.InDelta(t, 1.0, 1+bm.EffectiveValue(), delta) - } - return true - }) -} - -func TestAccessBaseManaVector_Update(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - // hold information about which events triggered - var updateEvents []*UpdatedEvent - - // when an event triggers, add it to the log - Events.Updated.Hook(event.NewClosure(func(ev *UpdatedEvent) { - updateEvents = append(updateEvents, ev) - })) - - randID := randNodeID() - // init vector to baseTime - bmv.SetMana(randID, NewAccessBaseMana(10.0, 0.0, baseTime)) - updateTime := baseTime.Add(time.Hour * 6) - err = bmv.Update(randID, updateTime) - - assert.NoError(t, err) - assert.Equal(t, 1, len(updateEvents)) - ev := updateEvents[0] - assert.Equal(t, randID, ev.NodeID) - assert.Equal(t, AccessMana, ev.ManaType) - assert.Equal(t, NewAccessBaseMana(10.0, 0.0, baseTime), ev.OldMana) - assert.InDelta(t, 5, ev.NewMana.BaseValue(), delta) - assert.InDelta(t, 3.465731, ev.NewMana.EffectiveValue(), delta) - assert.Equal(t, updateTime, ev.NewMana.LastUpdate()) -} - -func TestAccessBaseManaVector_UpdateError(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - // hold information about which events triggered - var updateEvents []*UpdatedEvent - - // when an event triggers, add it to the log - Events.Updated.Hook(event.NewClosure(func(ev *UpdatedEvent) { - updateEvents = append(updateEvents, ev) - })) - - randID := randNodeID() - updateTime := baseTime.Add(time.Hour * 6) - - // vector is empty ,but we want to update a non existing ID in it - err = bmv.Update(randID, updateTime) - assert.Error(t, err) - assert.Equal(t, ErrNodeNotFoundInBaseManaVector, err) - // no event triggered - assert.Empty(t, updateEvents) - - // init vector to baseTime - bmv.SetMana(randID, NewAccessBaseMana(10.0, 0.0, baseTime)) - // vector update to baseTime + 6 hours already - err = bmv.Update(randID, baseTime) - assert.Error(t, err) - assert.Equal(t, ErrAlreadyUpdated, err) -} - -func TestAccessBaseManaVector_UpdateAll(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - // hold information about which events triggered - var updateEvents []*UpdatedEvent - - // when an event triggers, add it to the log - Events.Updated.Hook(event.NewClosure(func(ev *UpdatedEvent) { - updateEvents = append(updateEvents, ev) - })) - - updatedNodeIds := map[identity.ID]interface{}{ - inputPledgeID1: 0, - inputPledgeID2: 0, - inputPledgeID3: 0, - } - - // init vector (values are not important) - bmv.SetMana(inputPledgeID1, NewAccessBaseMana(0.0, 0.0, baseTime)) - bmv.SetMana(inputPledgeID2, NewAccessBaseMana(0.0, 0.0, baseTime)) - bmv.SetMana(inputPledgeID3, NewAccessBaseMana(0.0, 0.0, baseTime)) - - updateTime := baseTime.Add(time.Hour) - err = bmv.UpdateAll(updateTime) - assert.NoError(t, err) - - for _, mana := range bmv.(*AccessBaseManaVector).M.Vector { - assert.Equal(t, updateTime, mana.LastUpdate()) - } - - assert.Equal(t, 3, len(updateEvents)) - for _, ev := range updateEvents { - assert.Contains(t, updatedNodeIds, ev.NodeID) - delete(updatedNodeIds, ev.NodeID) - } - assert.Empty(t, updatedNodeIds) -} - -func TestAccessBaseManaVector_GetMana(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - randID := randNodeID() - mana, _, err := bmv.GetMana(randID) - assert.Equal(t, 0.0, mana) - assert.NoError(t, err) - bmv.SetMana(randID, NewAccessBaseMana(0, 0, time.Time{})) - mana, _, err = bmv.GetMana(randID) - assert.Equal(t, 0.0, mana) - assert.NoError(t, err) - now := time.Now() - bmv.SetMana(randID, NewAccessBaseMana(1.0, 1.0, now)) - - mana, _, err = bmv.GetMana(randID, now) - assert.NoError(t, err) - assert.InDelta(t, 1.0, mana, delta) -} - -func TestAccessBaseManaVector_ForEach(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - for i := 0; i < 10000; i++ { - bmv.SetMana(randNodeID(), NewAccessBaseMana(1.0, 0.0, time.Time{})) - } - - // fore each should iterate over all elements - sum := 0.0 - bmv.ForEach(func(ID identity.ID, bm BaseMana) bool { - sum += bm.BaseValue() - return true - }) - assert.Equal(t, 10000.0, sum) - - // for each should stop if false is returned from callback - sum = 0.0 - bmv.ForEach(func(ID identity.ID, bm BaseMana) bool { - if sum >= 5000.0 { - return false - } - sum += bm.BaseValue() - return true - }) - - assert.Equal(t, 5000.0, sum) -} - -func TestAccessBaseManaVector_GetManaMap(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - // empty vector returns empty map - manaMap, _, err := bmv.GetManaMap() - assert.NoError(t, err) - assert.Empty(t, manaMap) - - now := time.Now() - nodeIDs := map[identity.ID]int{} - - for i := 0; i < 100; i++ { - id := randNodeID() - bmv.SetMana(id, NewAccessBaseMana(1.0, 1.0, now)) - nodeIDs[id] = 0 - } - - manaMap, _, err = bmv.GetManaMap(now) - assert.NoError(t, err) - assert.Equal(t, 100, len(manaMap)) - for nodeID, mana := range manaMap { - assert.InDelta(t, 1.0, mana, delta) - assert.Contains(t, nodeIDs, nodeID) - delete(nodeIDs, nodeID) - } - assert.Empty(t, nodeIDs) -} - -func TestAccessBaseManaVector_GetHighestManaNodes(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - nodeIDs := make([]identity.ID, 10) - - baseTime = time.Now() - - for i := 0; i < 10; i++ { - nodeIDs[i] = randNodeID() - bmv.SetMana(nodeIDs[i], NewAccessBaseMana(float64(i), float64(i), baseTime)) - } - - // requesting the top mana holder - result, _, err := bmv.GetHighestManaNodes(1) - assert.NoError(t, err) - assert.Equal(t, 1, len(result)) - assert.Equal(t, nodeIDs[9], result[0].ID) - assert.InDelta(t, 9.0, result[0].Mana, delta) - - // requesting top 3 mana holders - result, _, err = bmv.GetHighestManaNodes(3) - assert.NoError(t, err) - assert.Equal(t, 3, len(result)) - assert.InDelta(t, 9.0, result[0].Mana, delta) - for index, value := range result { - if index < 2 { - // it's greater than the next one - assert.True(t, value.Mana > result[index+1].Mana) - } - assert.Equal(t, nodeIDs[9-index], value.ID) - } - - // requesting more, than there currently are in the vector - result, _, err = bmv.GetHighestManaNodes(20) - assert.NoError(t, err) - assert.Equal(t, 10, len(result)) - for index, value := range result[:8] { - assert.Equal(t, nodeIDs[9-index], value.ID) - } -} - -func TestAccessBaseManaVector_GetHighestManaNodesFraction(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - nodeIDs := make([]identity.ID, 10) - - baseTime = time.Now() - - for i := 0; i < 10; i++ { - nodeIDs[i] = randNodeID() - bmv.SetMana(nodeIDs[i], NewAccessBaseMana(float64(i), float64(i), baseTime)) - } - - // requesting minus value - result, _, err := bmv.GetHighestManaNodesFraction(-0.1) - assert.NoError(t, err) - assert.Equal(t, 10, len(result)) - assert.Equal(t, nodeIDs[9], result[0].ID) - assert.InDelta(t, 9.0, result[0].Mana, delta) - - // requesting the holders of top 5% of mana - result, _, err = bmv.GetHighestManaNodesFraction(0.1) - assert.NoError(t, err) - assert.Equal(t, 1, len(result)) - assert.Equal(t, nodeIDs[9], result[0].ID) - assert.InDelta(t, 9.0, result[0].Mana, delta) - - // requesting holders of top 50% of mana - result, _, err = bmv.GetHighestManaNodesFraction(0.5) - assert.NoError(t, err) - assert.Equal(t, 3, len(result)) - assert.InDelta(t, 9.0, result[0].Mana, delta) - for index, value := range result { - if index < 2 { - // it's greater than the next one - assert.True(t, value.Mana > result[index+1].Mana) - } - assert.Equal(t, nodeIDs[9-index], value.ID) - } - - // requesting more, than there currently are in the vector - result, _, err = bmv.GetHighestManaNodesFraction(1.1) - assert.NoError(t, err) - assert.Equal(t, 10, len(result)) - for index, value := range result[:8] { - assert.Equal(t, nodeIDs[9-index], value.ID) - } -} - -func TestAccessBaseManaVector_SetMana(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - nodeIDs := make([]identity.ID, 10) - for i := 0; i < 10; i++ { - nodeIDs[i] = randNodeID() - bmv.SetMana(nodeIDs[i], NewAccessBaseMana(float64(i), float64(i), baseTime)) - } - for i := 0; i < 10; i++ { - assert.Equal(t, NewAccessBaseMana(float64(i), float64(i), baseTime), bmv.(*AccessBaseManaVector).M.Vector[nodeIDs[i]]) - } -} - -func TestAccessBaseManaVector_ToPersistables(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - id1 := randNodeID() - id2 := randNodeID() - data := map[identity.ID]float64{ - id1: 1, - id2: 10, - } - bmv.SetMana(id1, NewAccessBaseMana(data[id1], data[id1], baseTime)) - bmv.SetMana(id2, NewAccessBaseMana(data[id2], data[id2], baseTime)) - - persistables := bmv.ToPersistables() - - assert.Equal(t, 2, len(persistables)) - for _, p := range persistables { - assert.Equal(t, p.ManaType(), AccessMana) - assert.Equal(t, p.LastUpdated(), baseTime) - assert.Equal(t, 1, len(p.BaseValues())) - assert.Equal(t, 1, len(p.EffectiveValues())) - assert.Equal(t, data[p.NodeID()], p.BaseValues()[0]) - assert.Equal(t, data[p.NodeID()], p.EffectiveValues()[0]) - delete(data, p.NodeID()) - } - assert.Equal(t, 0, len(data)) -} - -func TestAccessBaseManaVector_FromPersistable(t *testing.T) { - t.Run("CASE: Happy path", func(t *testing.T) { - id := randNodeID() - p := NewPersistableBaseMana(id, AccessMana, []float64{10}, []float64{100}, baseTime) - - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - assert.False(t, bmv.Has(id)) - err = bmv.FromPersistable(p) - assert.NoError(t, err) - assert.True(t, bmv.Has(id)) - assert.Equal(t, 1, bmv.Size()) - bmValue := bmv.(*AccessBaseManaVector).M.Vector[id] - assert.Equal(t, 10.0, bmValue.BaseValue()) - assert.Equal(t, 100.0, bmValue.EffectiveValue()) - assert.Equal(t, baseTime, bmValue.LastUpdate()) - }) - - t.Run("CASE: Wrong type", func(t *testing.T) { - p := NewPersistableBaseMana(randNodeID(), ConsensusMana, []float64{0}, []float64{0}, baseTime) - - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - err = bmv.FromPersistable(p) - assert.Error(t, err) - assert.Contains(t, err.Error(), "has type Consensus instead of Access") - }) - - t.Run("CASE: Wrong number of base values", func(t *testing.T) { - p := NewPersistableBaseMana(randNodeID(), AccessMana, []float64{0, 0}, []float64{0}, baseTime) - - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - err = bmv.FromPersistable(p) - assert.Error(t, err) - assert.Contains(t, err.Error(), "has 2 base values instead of 1") - }) - - t.Run("CASE: Wrong number of effective values", func(t *testing.T) { - p := NewPersistableBaseMana(randNodeID(), AccessMana, []float64{0}, []float64{0, 0}, baseTime) - - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - err = bmv.FromPersistable(p) - assert.Error(t, err) - assert.Contains(t, err.Error(), "has 2 effective values instead of 1") - }) -} - -func TestAccessBaseManaVector_ToAndFromPersistable(t *testing.T) { - bmv, err := NewBaseManaVector(AccessMana) - assert.NoError(t, err) - id1 := randNodeID() - id2 := randNodeID() - data := map[identity.ID]float64{ - id1: 1, - id2: 10, - } - - bmv.SetMana(id1, NewAccessBaseMana(data[id1], data[id1], baseTime)) - - bmv.SetMana(id2, NewAccessBaseMana(data[id2], data[id2], baseTime)) - - persistables := bmv.ToPersistables() - - var restoredBmv BaseManaVector - restoredBmv, err = NewBaseManaVector(AccessMana) - assert.NoError(t, err) - - for _, p := range persistables { - err = restoredBmv.FromPersistable(p) - assert.NoError(t, err) - } - assert.Equal(t, bmv.(*AccessBaseManaVector).M.Vector, restoredBmv.(*AccessBaseManaVector).M.Vector) -} diff --git a/packages/mana/base.go b/packages/mana/base.go index 9c8a46abef..ae2687edee 100644 --- a/packages/mana/base.go +++ b/packages/mana/base.go @@ -8,12 +8,9 @@ import ( // BaseMana is an interface for a collection of base mana values of a single node. type BaseMana interface { - update(time.Time) error revoke(float64) error pledge(*TxInfo) float64 BaseValue() float64 - EffectiveValue() float64 - LastUpdate() time.Time } // ManaRetrievalFunc returns the mana value of a node with default weights. diff --git a/packages/mana/basevector.go b/packages/mana/basevector.go index c36b2c6600..2aa3fc240c 100644 --- a/packages/mana/basevector.go +++ b/packages/mana/basevector.go @@ -3,7 +3,6 @@ package mana import ( "time" - "github.com/cockroachdb/errors" "github.com/iotaledger/hive.go/generics/model" "github.com/iotaledger/hive.go/identity" ) @@ -20,14 +19,10 @@ type BaseManaVector interface { LoadSnapshot(map[identity.ID]*SnapshotNode) // Book books mana into the base mana vector. Book(*TxInfo) - // Update updates the mana entries for a particular node wrt time. - Update(identity.ID, time.Time) error - // UpdateAll updates all entries in the base mana vector wrt to time. - UpdateAll(time.Time) error // GetMana returns the mana value of a node with default weights. - GetMana(identity.ID, ...time.Time) (float64, time.Time, error) + GetMana(identity.ID) (float64, time.Time, error) // GetManaMap returns the map derived from the vector. - GetManaMap(...time.Time) (NodeMap, time.Time, error) + GetManaMap() (NodeMap, time.Time, error) // GetHighestManaNodes returns the n highest mana nodes in descending order. GetHighestManaNodes(uint) ([]Node, time.Time, error) // GetHighestManaNodesFraction returns the highest mana that own 'p' percent of total mana. @@ -45,13 +40,6 @@ type BaseManaVector interface { } // NewBaseManaVector creates and returns a new base mana vector for the specified type. -func NewBaseManaVector(vectorType Type) (BaseManaVector, error) { - switch vectorType { - case AccessMana: - return model.NewMutable[AccessBaseManaVector](&accessBaseManaVectorModel{Vector: make(map[identity.ID]*AccessBaseMana)}), nil - case ConsensusMana: - return model.NewMutable[ConsensusBaseManaVector](&consensusBaseManaVectorModel{Vector: make(map[identity.ID]*ConsensusBaseMana)}), nil - default: - return nil, errors.Errorf("error while creating base mana vector with type %d: %w", vectorType, ErrUnknownManaType) - } +func NewBaseManaVector() BaseManaVector { + return model.NewMutable[ManaBaseVector](&manaBaseVectorModel{Vector: make(map[identity.ID]*ManaBase)}) } diff --git a/packages/mana/consensusbase.go b/packages/mana/consensusbase.go deleted file mode 100644 index b0f1bc1591..0000000000 --- a/packages/mana/consensusbase.go +++ /dev/null @@ -1,61 +0,0 @@ -package mana - -import ( - "time" - - "github.com/iotaledger/hive.go/generics/model" -) - -// ConsensusBaseMana holds information about the consensus base mana values of a single node. -type ConsensusBaseMana struct { - model.Mutable[ConsensusBaseMana, *ConsensusBaseMana, consensusBaseManaModel] `serix:"0"` -} - -type consensusBaseManaModel struct { - BaseMana1 float64 `serix:"0"` -} - -func NewConsensusBaseMana(baseMana float64) *ConsensusBaseMana { - return model.NewMutable[ConsensusBaseMana](&consensusBaseManaModel{BaseMana1: baseMana}) -} - -func (c *ConsensusBaseMana) update(now time.Time) error { - panic("not implemented") -} - -func (c *ConsensusBaseMana) revoke(amount float64) error { - c.Lock() - defer c.Unlock() - //if c.BaseMana1-amount < 0.0 { - // return ErrBaseManaNegative - //} - c.M.BaseMana1 -= amount - return nil -} - -func (c *ConsensusBaseMana) pledge(tx *TxInfo) (pledged float64) { - c.Lock() - defer c.Unlock() - pledged = tx.sumInputs() - c.M.BaseMana1 += pledged - return pledged -} - -// BaseValue returns the base mana value (BM1). -func (c *ConsensusBaseMana) BaseValue() float64 { - c.RLock() - defer c.RUnlock() - return c.M.BaseMana1 -} - -// EffectiveValue returns the effective base mana value (EBM1). -func (c *ConsensusBaseMana) EffectiveValue() float64 { - panic("not implemented") -} - -// LastUpdate returns the last update time. -func (c *ConsensusBaseMana) LastUpdate() time.Time { - panic("not implemented") -} - -var _ BaseMana = &ConsensusBaseMana{} diff --git a/packages/mana/events.go b/packages/mana/events.go index 14a3c42ebd..c506d25429 100644 --- a/packages/mana/events.go +++ b/packages/mana/events.go @@ -54,8 +54,6 @@ type Event interface { ToJSONSerializable() interface{} // ToPersistable returns an event that can be persisted. ToPersistable() *PersistableEvent - // Timestamp returns the time of the event. - Timestamp() time.Time // String returns a human readable version of the event. String() string } @@ -239,9 +237,7 @@ type UpdatedEventJSON struct { // BaseManaJSON is a JSON serializable form of a BaseMana. type BaseManaJSON struct { - BaseMana float64 `json:"baseMana"` - EffectiveBaseMana float64 `json:"effectiveBaseMana"` - LastUpdated int64 `json:"lastUpdated"` + BaseMana float64 `json:"baseMana"` } // ToJSONSerializable returns a struct that can be serialized into JSON object. @@ -250,14 +246,10 @@ func (u *UpdatedEvent) ToJSONSerializable() interface{} { ManaType: u.ManaType.String(), NodeID: u.NodeID.String(), OldMana: &BaseManaJSON{ - BaseMana: u.OldMana.BaseValue(), - EffectiveBaseMana: u.OldMana.EffectiveValue(), - LastUpdated: u.OldMana.LastUpdate().Unix(), + BaseMana: u.OldMana.BaseValue(), }, NewMana: &BaseManaJSON{ - BaseMana: u.NewMana.BaseValue(), - EffectiveBaseMana: u.NewMana.EffectiveValue(), - LastUpdated: u.NewMana.LastUpdate().Unix(), + BaseMana: u.NewMana.BaseValue(), }, } } @@ -283,11 +275,6 @@ func (u *UpdatedEvent) Type() byte { return EventTypeUpdate } -// Timestamp returns time the event was fired. -func (u *UpdatedEvent) Timestamp() time.Time { - panic("not implemented") -} - var _ Event = &UpdatedEvent{} // EventSlice is a slice of events. diff --git a/packages/mana/events_test.go b/packages/mana/events_test.go index 37c10f9eba..63e3920e7c 100644 --- a/packages/mana/events_test.go +++ b/packages/mana/events_test.go @@ -92,8 +92,8 @@ func newRevokeEvent() *RevokedEvent { func newUpdateEvent() *UpdatedEvent { return &UpdatedEvent{ NodeID: randomNodeID(), - OldMana: &ConsensusBaseMana{}, - NewMana: &ConsensusBaseMana{}, + OldMana: NewManaBase(0.0), + NewMana: NewManaBase(0.0), ManaType: ConsensusMana, } } diff --git a/packages/mana/manabase.go b/packages/mana/manabase.go new file mode 100644 index 0000000000..4c03fe2699 --- /dev/null +++ b/packages/mana/manabase.go @@ -0,0 +1,45 @@ +package mana + +import ( + "github.com/iotaledger/hive.go/generics/model" +) + +// ManaBase holds information about the consensus base mana values of a single node. +type ManaBase struct { + model.Mutable[ManaBase, *ManaBase, manaBaseModel] `serix:"0"` +} + +type manaBaseModel struct { + Value float64 `serix:"0"` +} + +func NewManaBase(value float64) *ManaBase { + return model.NewMutable[ManaBase](&manaBaseModel{Value: value}) +} + +func (m *ManaBase) revoke(amount float64) error { + m.Lock() + defer m.Unlock() + //if m.BaseMana1-amount < 0.0 { + // return ErrBaseManaNegative + //} + m.M.Value -= amount + return nil +} + +func (m *ManaBase) pledge(tx *TxInfo) (pledged float64) { + m.Lock() + defer m.Unlock() + pledged = tx.sumInputs() + m.M.Value += pledged + return pledged +} + +// BaseValue returns the base mana value (BM1). +func (m *ManaBase) BaseValue() float64 { + m.RLock() + defer m.RUnlock() + return m.M.Value +} + +var _ BaseMana = &ManaBase{} diff --git a/packages/mana/consensusbase_test.go b/packages/mana/manabase_test.go similarity index 93% rename from packages/mana/consensusbase_test.go rename to packages/mana/manabase_test.go index 27837212fa..b15354f1d9 100644 --- a/packages/mana/consensusbase_test.go +++ b/packages/mana/manabase_test.go @@ -9,7 +9,7 @@ import ( ) func TestRevoke_Consensus(t *testing.T) { - bm := NewConsensusBaseMana(1.0) + bm := NewManaBase(1.0) err := bm.revoke(1.0) assert.NoError(t, err) // values are only valid for default coefficients of 0.00003209 and t = 6 hours @@ -17,7 +17,7 @@ func TestRevoke_Consensus(t *testing.T) { } func TestRevokeNegativeBalance_Consensus(t *testing.T) { - bm := NewConsensusBaseMana(0.0) + bm := NewManaBase(0.0) err := bm.revoke(1.0) assert.NoError(t, err) @@ -26,7 +26,7 @@ func TestRevokeNegativeBalance_Consensus(t *testing.T) { func TestPledgeAndUpdateRegularOldFunds_Consensus(t *testing.T) { _baseTime := time.Now() - bm := NewConsensusBaseMana(1.0) + bm := NewManaBase(1.0) // transaction pledges mana at t=6 hours with 3 inputs. _txInfo := &TxInfo{ diff --git a/packages/mana/consensusbasevector.go b/packages/mana/manabasevector.go similarity index 59% rename from packages/mana/consensusbasevector.go rename to packages/mana/manabasevector.go index e2a624b1f6..8639460b12 100644 --- a/packages/mana/consensusbasevector.go +++ b/packages/mana/manabasevector.go @@ -11,45 +11,45 @@ import ( "github.com/iotaledger/hive.go/identity" ) -// ConsensusBaseManaVector represents a base mana vector. -type ConsensusBaseManaVector struct { - model.Mutable[ConsensusBaseManaVector, *ConsensusBaseManaVector, consensusBaseManaVectorModel] `serix:"0"` +// ManaBaseVector represents a base mana vector. +type ManaBaseVector struct { + model.Mutable[ManaBaseVector, *ManaBaseVector, manaBaseVectorModel] `serix:"0"` } -type consensusBaseManaVectorModel struct { - Vector map[identity.ID]*ConsensusBaseMana `serix:"0"` +type manaBaseVectorModel struct { + Vector map[identity.ID]*ManaBase `serix:"0"` } // Vector returns the ConsensusBaseMana vector. -func (c *ConsensusBaseManaVector) Vector() map[identity.ID]*ConsensusBaseMana { - return c.M.Vector +func (m *ManaBaseVector) Vector() map[identity.ID]*ManaBase { + return m.M.Vector } // Type returns the type of this mana vector. -func (c *ConsensusBaseManaVector) Type() Type { +func (m *ManaBaseVector) Type() Type { return ConsensusMana } // Size returns the size of this mana vector. -func (c *ConsensusBaseManaVector) Size() int { - c.RLock() - defer c.RUnlock() - return len(c.M.Vector) +func (m *ManaBaseVector) Size() int { + m.RLock() + defer m.RUnlock() + return len(m.M.Vector) } // Has returns if the given node has mana defined in the vector. -func (c *ConsensusBaseManaVector) Has(nodeID identity.ID) bool { - c.RLock() - defer c.RUnlock() - _, exists := c.M.Vector[nodeID] +func (m *ManaBaseVector) Has(nodeID identity.ID) bool { + m.RLock() + defer m.RUnlock() + _, exists := m.M.Vector[nodeID] return exists } // // BuildPastBaseVector builds a consensus base mana vector from past events upto time `t`. // // `eventLogs` is expected to be sorted chronologically. // func (c *ConsensusBaseManaVector) BuildPastBaseVector(eventsLog []Event, t time.Time) error { -// if c.vector == nil { -// c.vector = make(map[identity.ID]*ConsensusBaseMana) +// if m.vector == nil { +// m.vector = make(map[identity.ID]*ConsensusBaseMana) // } // for _, _ev := range eventsLog { // switch _ev.Type() { @@ -58,19 +58,19 @@ func (c *ConsensusBaseManaVector) Has(nodeID identity.ID) bool { // if ev.Time.After(t) { // return nil // } -// if _, exist := c.vector[ev.NodeID]; !exist { -// c.vector[ev.NodeID] = &ConsensusBaseMana{} +// if _, exist := m.vector[ev.NodeID]; !exist { +// m.vector[ev.NodeID] = &ConsensusBaseMana{} // } -// c.vector[ev.NodeID].pledge(txInfoFromPledgeEvent(ev)) +// m.vector[ev.NodeID].pledge(txInfoFromPledgeEvent(ev)) // case EventTypeRevoke: // ev := _ev.(*RevokedEvent) // if ev.Time.After(t) { // return nil // } -// if _, exist := c.vector[ev.NodeID]; !exist { -// c.vector[ev.NodeID] = &ConsensusBaseMana{} +// if _, exist := m.vector[ev.NodeID]; !exist { +// m.vector[ev.NodeID] = &ConsensusBaseMana{} // } -// err := c.vector[ev.NodeID].revoke(ev.Amount, ev.Time) +// err := m.vector[ev.NodeID].revoke(ev.Amount, ev.Time) // if err != nil { // return err // } @@ -100,9 +100,9 @@ func txInfoFromPledgeEvent(ev *PledgedEvent) *TxInfo { } // LoadSnapshot loads the snapshot. -func (c *ConsensusBaseManaVector) LoadSnapshot(snapshot map[identity.ID]*SnapshotNode) { - c.Lock() - defer c.Unlock() +func (m *ManaBaseVector) LoadSnapshot(snapshot map[identity.ID]*SnapshotNode) { + m.Lock() + defer m.Unlock() for nodeID, records := range snapshot { var value float64 @@ -114,67 +114,67 @@ func (c *ConsensusBaseManaVector) LoadSnapshot(snapshot map[identity.ID]*Snapsho NodeID: nodeID, Amount: record.Value, Time: record.Timestamp, - ManaType: c.Type(), + ManaType: m.Type(), TransactionID: record.TxID, }) } - c.M.Vector[nodeID] = model.NewMutable[ConsensusBaseMana](&consensusBaseManaModel{BaseMana1: value}) + m.M.Vector[nodeID] = NewManaBase(value) } } // Book books mana for a transaction. -func (c *ConsensusBaseManaVector) Book(txInfo *TxInfo) { +func (m *ManaBaseVector) Book(txInfo *TxInfo) { // gather events to be triggered once the lock is lifted var revokeEvents []*RevokedEvent var pledgeEvents []*PledgedEvent var updateEvents []*UpdatedEvent // only lock mana vector while we are working with it func() { - c.Lock() - defer c.Unlock() + m.Lock() + defer m.Unlock() // first, revoke mana from previous owners for _, inputInfo := range txInfo.InputInfos { // which node did the input pledge mana to? - oldPledgeNodeID := inputInfo.PledgeID[c.Type()] - if _, exist := c.M.Vector[oldPledgeNodeID]; !exist { + oldPledgeNodeID := inputInfo.PledgeID[m.Type()] + if _, exist := m.M.Vector[oldPledgeNodeID]; !exist { // first time we see this node - c.M.Vector[oldPledgeNodeID] = &ConsensusBaseMana{} - c.M.Vector[oldPledgeNodeID].Init() + m.M.Vector[oldPledgeNodeID] = &ManaBase{} + m.M.Vector[oldPledgeNodeID].Init() } // save old mana - oldMana := *c.M.Vector[oldPledgeNodeID] + oldMana := *m.M.Vector[oldPledgeNodeID] // revoke BM1 - err := c.M.Vector[oldPledgeNodeID].revoke(inputInfo.Amount) + err := m.M.Vector[oldPledgeNodeID].revoke(inputInfo.Amount) if errors.Is(err, ErrBaseManaNegative) { panic(fmt.Sprintf("Revoking %f base mana 1 from node %s results in negative balance", inputInfo.Amount, oldPledgeNodeID.String())) } // save events for later triggering - revokeEvents = append(revokeEvents, &RevokedEvent{oldPledgeNodeID, inputInfo.Amount, txInfo.TimeStamp, c.Type(), txInfo.TransactionID, inputInfo.InputID}) - updateEvents = append(updateEvents, &UpdatedEvent{oldPledgeNodeID, &oldMana, c.M.Vector[oldPledgeNodeID], c.Type()}) + revokeEvents = append(revokeEvents, &RevokedEvent{oldPledgeNodeID, inputInfo.Amount, txInfo.TimeStamp, m.Type(), txInfo.TransactionID, inputInfo.InputID}) + updateEvents = append(updateEvents, &UpdatedEvent{oldPledgeNodeID, &oldMana, m.M.Vector[oldPledgeNodeID], m.Type()}) } // second, pledge mana to new nodes - newPledgeNodeID := txInfo.PledgeID[c.Type()] - if _, exist := c.M.Vector[newPledgeNodeID]; !exist { + newPledgeNodeID := txInfo.PledgeID[m.Type()] + if _, exist := m.M.Vector[newPledgeNodeID]; !exist { // first time we see this node - c.M.Vector[newPledgeNodeID] = NewConsensusBaseMana(0) + m.M.Vector[newPledgeNodeID] = NewManaBase(0) } // save it for proper event trigger - oldMana := *c.M.Vector[newPledgeNodeID] + oldMana := *m.M.Vector[newPledgeNodeID] // actually pledge and update - pledged := c.M.Vector[newPledgeNodeID].pledge(txInfo) + pledged := m.M.Vector[newPledgeNodeID].pledge(txInfo) pledgeEvents = append(pledgeEvents, &PledgedEvent{ NodeID: newPledgeNodeID, Amount: pledged, Time: txInfo.TimeStamp, - ManaType: c.Type(), + ManaType: m.Type(), TransactionID: txInfo.TransactionID, }) updateEvents = append(updateEvents, &UpdatedEvent{ NodeID: newPledgeNodeID, OldMana: &oldMana, - NewMana: c.M.Vector[newPledgeNodeID], - ManaType: c.Type(), + NewMana: m.M.Vector[newPledgeNodeID], + ManaType: m.Type(), }) }() @@ -190,31 +190,21 @@ func (c *ConsensusBaseManaVector) Book(txInfo *TxInfo) { } } -// Update updates the mana entries for a particular node wrt time. -func (c *ConsensusBaseManaVector) Update(nodeID identity.ID, t time.Time) error { - panic("not implemented") -} - -// UpdateAll updates all entries in the base mana vector wrt to `t`. -func (c *ConsensusBaseManaVector) UpdateAll(t time.Time) error { - panic("not implemented") -} - // GetMana returns the Effective Base Mana. -func (c *ConsensusBaseManaVector) GetMana(nodeID identity.ID, optionalUpdateTime ...time.Time) (float64, time.Time, error) { - c.Lock() - defer c.Unlock() - mana, err := c.getMana(nodeID) +func (m *ManaBaseVector) GetMana(nodeID identity.ID) (float64, time.Time, error) { + m.Lock() + defer m.Unlock() + mana, err := m.getMana(nodeID) return mana, time.Now(), err } // GetManaMap returns mana perception of the node. -func (c *ConsensusBaseManaVector) GetManaMap(optionalUpdateTime ...time.Time) (res NodeMap, t time.Time, err error) { - c.Lock() - defer c.Unlock() +func (m *ManaBaseVector) GetManaMap() (res NodeMap, t time.Time, err error) { + m.Lock() + defer m.Unlock() t = time.Now() - res = make(map[identity.ID]float64, len(c.M.Vector)) - for ID, val := range c.M.Vector { + res = make(map[identity.ID]float64, len(m.M.Vector)) + for ID, val := range m.M.Vector { res[ID] = val.BaseValue() } return @@ -223,15 +213,15 @@ func (c *ConsensusBaseManaVector) GetManaMap(optionalUpdateTime ...time.Time) (r // GetHighestManaNodes return the n highest mana nodes in descending order. // It also updates the mana values for each node. // If n is zero, it returns all nodes. -func (c *ConsensusBaseManaVector) GetHighestManaNodes(n uint) (res []Node, t time.Time, err error) { +func (m *ManaBaseVector) GetHighestManaNodes(n uint) (res []Node, t time.Time, err error) { t = time.Now() err = func() error { // don't lock the vector after this func returns - c.Lock() - defer c.Unlock() - for ID := range c.M.Vector { + m.Lock() + defer m.Unlock() + for ID := range m.M.Vector { var mana float64 - mana, err = c.getMana(ID) + mana, err = m.getMana(ID) if err != nil { return err } @@ -260,22 +250,22 @@ func (c *ConsensusBaseManaVector) GetHighestManaNodes(n uint) (res []Node, t tim // GetHighestManaNodesFraction returns the highest mana that own 'p' percent of total mana. // It also updates the mana values for each node. // If p is zero or greater than one, it returns all nodes. -func (c *ConsensusBaseManaVector) GetHighestManaNodesFraction(p float64) (res []Node, t time.Time, err error) { +func (m *ManaBaseVector) GetHighestManaNodesFraction(p float64) (res []Node, t time.Time, err error) { emptyNodeID := identity.ID{} totalMana := 0.0 t = time.Now() err = func() error { // don't lock the vector after this func returns - c.Lock() - defer c.Unlock() - for ID := range c.M.Vector { + m.Lock() + defer m.Unlock() + for ID := range m.M.Vector { // skip the empty node ID if bytes.Equal(ID[:], emptyNodeID[:]) { continue } var mana float64 - mana, err = c.getMana(ID) + mana, err = m.getMana(ID) if err != nil { return err } @@ -311,18 +301,18 @@ func (c *ConsensusBaseManaVector) GetHighestManaNodesFraction(p float64) (res [] } // SetMana sets the base mana for a node. -func (c *ConsensusBaseManaVector) SetMana(nodeID identity.ID, bm BaseMana) { - c.Lock() - defer c.Unlock() - c.M.Vector[nodeID] = bm.(*ConsensusBaseMana) +func (m *ManaBaseVector) SetMana(nodeID identity.ID, bm BaseMana) { + m.Lock() + defer m.Unlock() + m.M.Vector[nodeID] = bm.(*ManaBase) } // ForEach iterates over the vector and calls the provided callback. -func (c *ConsensusBaseManaVector) ForEach(callback func(ID identity.ID, bm BaseMana) bool) { +func (m *ManaBaseVector) ForEach(callback func(ID identity.ID, bm BaseMana) bool) { // lock to be on the safe side, although callback might just read - c.Lock() - defer c.Unlock() - for nodeID, baseMana := range c.M.Vector { + m.Lock() + defer m.Unlock() + for nodeID, baseMana := range m.M.Vector { if !callback(nodeID, baseMana) { return } @@ -330,19 +320,19 @@ func (c *ConsensusBaseManaVector) ForEach(callback func(ID identity.ID, bm BaseM } // ToPersistables converts the baseManaVector to a list of persistable mana objects. -func (c *ConsensusBaseManaVector) ToPersistables() []*PersistableBaseMana { - c.RLock() - defer c.RUnlock() +func (m *ManaBaseVector) ToPersistables() []*PersistableBaseMana { + m.RLock() + defer m.RUnlock() var result []*PersistableBaseMana - for nodeID, bm := range c.M.Vector { - pbm := NewPersistableBaseMana(nodeID, c.Type(), []float64{bm.BaseValue()}, nil, time.Time{}) + for nodeID, bm := range m.M.Vector { + pbm := NewPersistableBaseMana(nodeID, m.Type(), []float64{bm.BaseValue()}, nil, time.Time{}) result = append(result, pbm) } return result } // FromPersistable fills the ConsensusBaseManaVector from persistable mana objects. -func (c *ConsensusBaseManaVector) FromPersistable(p *PersistableBaseMana) (err error) { +func (m *ManaBaseVector) FromPersistable(p *PersistableBaseMana) (err error) { if p.ManaType() != ConsensusMana { err = errors.Errorf("persistable mana object has type %s instead of %s", p.ManaType().String(), ConsensusMana.String()) return @@ -351,33 +341,33 @@ func (c *ConsensusBaseManaVector) FromPersistable(p *PersistableBaseMana) (err e err = errors.Errorf("persistable mana object has %d base values instead of 1", len(p.BaseValues())) return } - c.Lock() - defer c.Unlock() - c.M.Vector[p.NodeID()] = model.NewMutable[ConsensusBaseMana](&consensusBaseManaModel{BaseMana1: p.BaseValues()[0]}) + m.Lock() + defer m.Unlock() + m.M.Vector[p.NodeID()] = model.NewMutable[ManaBase](&manaBaseModel{Value: p.BaseValues()[0]}) return } // RemoveZeroNodes removes the zero mana nodes from the vector. -func (c *ConsensusBaseManaVector) RemoveZeroNodes() { - c.Lock() - defer c.Unlock() - for nodeID, baseMana := range c.M.Vector { +func (m *ManaBaseVector) RemoveZeroNodes() { + m.Lock() + defer m.Unlock() + for nodeID, baseMana := range m.M.Vector { if baseMana.BaseValue() == 0 { - delete(c.M.Vector, nodeID) + delete(m.M.Vector, nodeID) } } } -var _ BaseManaVector = &ConsensusBaseManaVector{} +var _ BaseManaVector = &ManaBaseVector{} // // Region Internal methods //// // getMana returns the consensus mana. -func (c *ConsensusBaseManaVector) getMana(nodeID identity.ID) (float64, error) { - if _, exist := c.M.Vector[nodeID]; !exist { +func (m *ManaBaseVector) getMana(nodeID identity.ID) (float64, error) { + if _, exist := m.M.Vector[nodeID]; !exist { return 0.0, ErrNodeNotFoundInBaseManaVector } - baseMana := c.M.Vector[nodeID] + baseMana := m.M.Vector[nodeID] return baseMana.BaseValue(), nil } diff --git a/packages/mana/consensusbasevector_test.go b/packages/mana/manabasevector_test.go similarity index 70% rename from packages/mana/consensusbasevector_test.go rename to packages/mana/manabasevector_test.go index 41e8f4c7b8..5e736f1c1b 100644 --- a/packages/mana/consensusbasevector_test.go +++ b/packages/mana/manabasevector_test.go @@ -4,45 +4,109 @@ import ( "testing" "time" + "github.com/iotaledger/goshimmer/packages/ledger/utxo" "github.com/iotaledger/hive.go/generics/event" "github.com/iotaledger/hive.go/identity" "github.com/stretchr/testify/assert" ) +var ( + baseTime = time.Now() + inputTime = baseTime.Add(time.Hour * -200) + txTime = baseTime.Add(time.Hour * 6) + txPledgeID = randNodeID() + inputPledgeID1 = randNodeID() + inputPledgeID2 = randNodeID() + inputPledgeID3 = randNodeID() + beforeBookingAmount = map[identity.ID]float64{ + txPledgeID: 0, + inputPledgeID1: 5.0, + inputPledgeID2: 3.0, + inputPledgeID3: 2.0, + } + afterBookingAmount = map[identity.ID]float64{ + txPledgeID: 10.0, + inputPledgeID1: 0, + inputPledgeID2: 0, + inputPledgeID3: 0, + } + txInfo = &TxInfo{ + TimeStamp: txTime, + TransactionID: randomTxID(), + TotalBalance: 10.0, + PledgeID: map[Type]identity.ID{ + AccessMana: txPledgeID, + ConsensusMana: txPledgeID, + }, + InputInfos: []InputInfo{ + { + // funds have been sitting here for couple days... + TimeStamp: inputTime, + Amount: beforeBookingAmount[inputPledgeID1], + PledgeID: map[Type]identity.ID{ + AccessMana: inputPledgeID1, + ConsensusMana: inputPledgeID1, + }, + InputID: utxo.NewOutputID(randomTxID(), 0), + }, + { + // funds have been sitting here for couple days... + TimeStamp: inputTime, + Amount: beforeBookingAmount[inputPledgeID2], + PledgeID: map[Type]identity.ID{ + AccessMana: inputPledgeID2, + ConsensusMana: inputPledgeID2, + }, + InputID: utxo.NewOutputID(randomTxID(), 0), + }, + { + // funds have been sitting here for couple days... + TimeStamp: inputTime, + Amount: beforeBookingAmount[inputPledgeID3], + PledgeID: map[Type]identity.ID{ + AccessMana: inputPledgeID3, + ConsensusMana: inputPledgeID3, + }, + InputID: utxo.NewOutputID(randomTxID(), 0), + }, + }, + } +) + +func randNodeID() identity.ID { + return identity.GenerateIdentity().ID() +} + func TestNewBaseManaVector_Consensus(t *testing.T) { - bmvCons, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmvCons := NewBaseManaVector() assert.Equal(t, ConsensusMana, bmvCons.Type()) - assert.Equal(t, map[identity.ID]*ConsensusBaseMana{}, bmvCons.(*ConsensusBaseManaVector).M.Vector) + assert.Equal(t, map[identity.ID]*ManaBase{}, bmvCons.(*ManaBaseVector).M.Vector) } func TestConsensusBaseManaVector_Type(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() vectorType := bmv.Type() assert.Equal(t, ConsensusMana, vectorType) } func TestConsensusBaseManaVector_Size(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() assert.Equal(t, 0, bmv.Size()) for i := 0; i < 10; i++ { - bmv.SetMana(randNodeID(), NewConsensusBaseMana(float64(i))) + bmv.SetMana(randNodeID(), NewManaBase(float64(i))) } assert.Equal(t, 10, bmv.Size()) } func TestConsensusBaseManaVector_Has(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() randID := randNodeID() has := bmv.Has(randID) assert.False(t, has) - bmv.SetMana(randID, NewConsensusBaseMana(0)) + bmv.SetMana(randID, NewManaBase(0)) has = bmv.Has(randID) assert.True(t, has) } @@ -66,13 +130,12 @@ func TestConsensusBaseManaVector_Book(t *testing.T) { pledgeEvents = append(pledgeEvents, ev) })) - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() // init vector to inputTime with pledged beforeBookingAmount - bmv.SetMana(inputPledgeID1, NewConsensusBaseMana(beforeBookingAmount[inputPledgeID1])) - bmv.SetMana(inputPledgeID2, NewConsensusBaseMana(beforeBookingAmount[inputPledgeID2])) - bmv.SetMana(inputPledgeID3, NewConsensusBaseMana(beforeBookingAmount[inputPledgeID3])) + bmv.SetMana(inputPledgeID1, NewManaBase(beforeBookingAmount[inputPledgeID1])) + bmv.SetMana(inputPledgeID2, NewManaBase(beforeBookingAmount[inputPledgeID2])) + bmv.SetMana(inputPledgeID3, NewManaBase(beforeBookingAmount[inputPledgeID3])) // drop all recorded updatedEvents updateEvents = []*UpdatedEvent{} @@ -129,19 +192,18 @@ func TestConsensusBaseManaVector_Book(t *testing.T) { } func TestConsensusBaseManaVector_GetMana(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() randID := randNodeID() mana, _, err := bmv.GetMana(randID) assert.Equal(t, 0.0, mana) assert.Error(t, err) - bmv.SetMana(randID, NewConsensusBaseMana(0)) + bmv.SetMana(randID, NewManaBase(0)) mana, _, err = bmv.GetMana(randID) assert.NoError(t, err) assert.Equal(t, 0.0, mana) - bmv.SetMana(randID, NewConsensusBaseMana(10.0)) + bmv.SetMana(randID, NewManaBase(10.0)) mana, _, err = bmv.GetMana(randID) assert.NoError(t, err) @@ -149,11 +211,10 @@ func TestConsensusBaseManaVector_GetMana(t *testing.T) { } func TestConsensusBaseManaVector_ForEach(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() for i := 0; i < 10000; i++ { - bmv.SetMana(randNodeID(), NewConsensusBaseMana(1.0)) + bmv.SetMana(randNodeID(), NewManaBase(1.0)) } // fore each should iterate over all elements @@ -178,8 +239,7 @@ func TestConsensusBaseManaVector_ForEach(t *testing.T) { } func TestConsensusBaseManaVector_GetManaMap(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() // empty vector returns empty map manaMap, _, err := bmv.GetManaMap() @@ -190,7 +250,7 @@ func TestConsensusBaseManaVector_GetManaMap(t *testing.T) { for i := 0; i < 100; i++ { id := randNodeID() - bmv.SetMana(id, NewConsensusBaseMana(10.0)) + bmv.SetMana(id, NewManaBase(10.0)) nodeIDs[id] = 0 } @@ -206,14 +266,13 @@ func TestConsensusBaseManaVector_GetManaMap(t *testing.T) { } func TestConsensusBaseManaVector_GetHighestManaNodes(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() nodeIDs := make([]identity.ID, 10) for i := 0; i < 10; i++ { nodeIDs[i] = randNodeID() - bmv.SetMana(nodeIDs[i], NewConsensusBaseMana(float64(i))) + bmv.SetMana(nodeIDs[i], NewManaBase(float64(i))) } // requesting the top mana holder @@ -246,8 +305,7 @@ func TestConsensusBaseManaVector_GetHighestManaNodes(t *testing.T) { } func TestConsensusBaseManaVector_GetHighestManaNodesFraction(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() nodeIDs := make([]identity.ID, 10) @@ -255,7 +313,7 @@ func TestConsensusBaseManaVector_GetHighestManaNodesFraction(t *testing.T) { for i := 0; i < 10; i++ { nodeIDs[i] = randNodeID() - bmv.SetMana(nodeIDs[i], NewConsensusBaseMana(float64(i))) + bmv.SetMana(nodeIDs[i], NewManaBase(float64(i))) } // requesting minus value @@ -295,29 +353,27 @@ func TestConsensusBaseManaVector_GetHighestManaNodesFraction(t *testing.T) { } func TestConsensusBaseManaVector_SetMana(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() nodeIDs := make([]identity.ID, 10) for i := 0; i < 10; i++ { nodeIDs[i] = randNodeID() - bmv.SetMana(nodeIDs[i], NewConsensusBaseMana(float64(i))) + bmv.SetMana(nodeIDs[i], NewManaBase(float64(i))) } for i := 0; i < 10; i++ { - assert.Equal(t, NewConsensusBaseMana(float64(i)), bmv.(*ConsensusBaseManaVector).M.Vector[nodeIDs[i]]) + assert.Equal(t, NewManaBase(float64(i)), bmv.(*ManaBaseVector).M.Vector[nodeIDs[i]]) } } func TestConsensusBaseManaVector_ToPersistables(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() id1 := randNodeID() id2 := randNodeID() data := map[identity.ID]float64{ id1: 1, id2: 10, } - bmv.SetMana(id1, NewConsensusBaseMana(data[id1])) - bmv.SetMana(id2, NewConsensusBaseMana(data[id2])) + bmv.SetMana(id1, NewManaBase(data[id1])) + bmv.SetMana(id2, NewManaBase(data[id2])) persistables := bmv.ToPersistables() @@ -335,23 +391,21 @@ func TestConsensusBaseManaVector_FromPersistable(t *testing.T) { t.Run("CASE: Happy path", func(t *testing.T) { id := randNodeID() p := NewPersistableBaseMana(id, ConsensusMana, []float64{10}, []float64{100}, baseTime) - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() assert.False(t, bmv.Has(id)) - err = bmv.FromPersistable(p) + err := bmv.FromPersistable(p) assert.NoError(t, err) assert.True(t, bmv.Has(id)) assert.Equal(t, 1, bmv.Size()) - bmValue := bmv.(*ConsensusBaseManaVector).M.Vector[id] + bmValue := bmv.(*ManaBaseVector).M.Vector[id] assert.Equal(t, 10.0, bmValue.BaseValue()) }) t.Run("CASE: Wrong type", func(t *testing.T) { p := NewPersistableBaseMana(randNodeID(), AccessMana, []float64{0}, []float64{0}, baseTime) - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() - err = bmv.FromPersistable(p) + err := bmv.FromPersistable(p) assert.Error(t, err) assert.Contains(t, err.Error(), "has type Access instead of Consensus") }) @@ -359,36 +413,33 @@ func TestConsensusBaseManaVector_FromPersistable(t *testing.T) { t.Run("CASE: Wrong number of base values", func(t *testing.T) { p := NewPersistableBaseMana(randNodeID(), ConsensusMana, []float64{0, 0}, []float64{0}, baseTime) - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() - err = bmv.FromPersistable(p) + err := bmv.FromPersistable(p) assert.Error(t, err) assert.Contains(t, err.Error(), "has 2 base values instead of 1") }) } func TestConsensusBaseManaVector_ToAndFromPersistable(t *testing.T) { - bmv, err := NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + bmv := NewBaseManaVector() id1 := randNodeID() id2 := randNodeID() data := map[identity.ID]float64{ id1: 1, id2: 10, } - bmv.SetMana(id1, NewConsensusBaseMana(data[id1])) - bmv.SetMana(id2, NewConsensusBaseMana(data[id2])) + bmv.SetMana(id1, NewManaBase(data[id1])) + bmv.SetMana(id2, NewManaBase(data[id2])) persistables := bmv.ToPersistables() var restoredBmv BaseManaVector - restoredBmv, err = NewBaseManaVector(ConsensusMana) - assert.NoError(t, err) + restoredBmv = NewBaseManaVector() for _, p := range persistables { - err = restoredBmv.FromPersistable(p) + err := restoredBmv.FromPersistable(p) assert.NoError(t, err) } - assert.Equal(t, bmv.(*ConsensusBaseManaVector).M.Vector, restoredBmv.(*ConsensusBaseManaVector).M.Vector) + assert.Equal(t, bmv.(*ManaBaseVector).M.Vector, restoredBmv.(*ManaBaseVector).M.Vector) } diff --git a/packages/mana/consensusbasevectormetadata.go b/packages/mana/manabasevectormetadata.go similarity index 100% rename from packages/mana/consensusbasevectormetadata.go rename to packages/mana/manabasevectormetadata.go diff --git a/packages/mana/consensusbasevectormetadata_test.go b/packages/mana/manabasevectormetadata_test.go similarity index 100% rename from packages/mana/consensusbasevectormetadata_test.go rename to packages/mana/manabasevectormetadata_test.go diff --git a/packages/mana/parameters.go b/packages/mana/parameters.go deleted file mode 100644 index 70fc92ebdc..0000000000 --- a/packages/mana/parameters.go +++ /dev/null @@ -1,50 +0,0 @@ -package mana - -const ( - // Description: Taking (x * EBM1 + (1-x) * EBM2) into account when getting the mana value. - - // OnlyMana1 takes only EBM1 into account when getting the mana values. - OnlyMana1 float64 = 1.0 - // OnlyMana2 takes only EBM2 into account when getting the mana values. - OnlyMana2 float64 = 0.0 - // Mixed takes both EBM1 and EBM2 into account (50-50) when getting the mana values. - Mixed float64 = 0.5 - - // DeltaStopUpdate stops the update of the effective mana value if it is in the delta interval of the the base mana - // value. Base mana can only be an integer, and effective mana tends to this integer value over time if there are no - // pledges or revokes. - // It is used primarily for consensus mana, since for access mana, base mana changes wrt to time. The updates for - // access mana stop when the base mana value AND the effective value is in DeltaStopUpdates interval of 0. - DeltaStopUpdate float64 = 0.001 - - // MinEffectiveMana defines the threshold to consider an effective mana value zero. - MinEffectiveMana = 0.001 - // MinBaseMana defines the threshold to consider the base mana value zero. - MinBaseMana = 0.001 -) - -var ( - // default values are for half life of 6 hours, unit is 1/s - // exponential moving average coefficient for Mana 1 calculation (used in consensus mana). - emaCoeff1 = 0.00003209 - // exponential moving average coefficient for Mana 2 calculation (used in access mana). - emaCoeff2 = 0.00003209 - // Decay is the mana decay (gamma) (used in access mana), in 1/sec. - Decay = 0.00003209 -) - -// SetCoefficients sets the coefficients for mana calculation. -func SetCoefficients(ema1 float64, ema2 float64, dec float64) { - if ema1 <= 0.0 { - panic("invalid emaCoefficient1 parameter, value must be greater than 0.") - } - if ema2 <= 0.0 { - panic("invalid emaCoefficient2 parameter, value must be greater than 0.") - } - if dec <= 0.0 { - panic("invalid decay (gamma) parameter, value must be greater than 0.") - } - emaCoeff1 = ema1 - emaCoeff2 = ema2 - Decay = dec -} diff --git a/packages/shutdown/order.go b/packages/shutdown/order.go index dc45ff3a05..6d77e1fe0f 100644 --- a/packages/shutdown/order.go +++ b/packages/shutdown/order.go @@ -35,8 +35,6 @@ const ( PriorityBroadcast // PrioritySynchronization defines the shutdown priority for synchronization. PrioritySynchronization - // PriorityManaRefresher defines the shutdown priority for the manarefresher plugin. - PriorityManaRefresher // PriorityActivity defines the shutdown priority for the activity plugin. PriorityActivity // PrioritySpammer defines the shutdown priority for spammer. diff --git a/plugins/core.go b/plugins/core.go index 03f8c2a547..05349dcd31 100644 --- a/plugins/core.go +++ b/plugins/core.go @@ -15,7 +15,6 @@ import ( "github.com/iotaledger/goshimmer/plugins/gracefulshutdown" "github.com/iotaledger/goshimmer/plugins/logger" "github.com/iotaledger/goshimmer/plugins/manaeventlogger" - "github.com/iotaledger/goshimmer/plugins/manarefresher" "github.com/iotaledger/goshimmer/plugins/manualpeering" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/metrics" @@ -45,7 +44,6 @@ var Core = node.Plugins( gossip.Plugin, firewall.Plugin, messagelayer.ManaPlugin, - manarefresher.Plugin, faucet.Plugin, metrics.Plugin, spammer.Plugin, diff --git a/plugins/dashboard/explorer_routes.go b/plugins/dashboard/explorer_routes.go index 0ef7ab0d34..f89ce9ea42 100644 --- a/plugins/dashboard/explorer_routes.go +++ b/plugins/dashboard/explorer_routes.go @@ -17,9 +17,7 @@ import ( "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm/indexer" "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/chat" - "github.com/iotaledger/goshimmer/plugins/messagelayer" ledgerstateAPI "github.com/iotaledger/goshimmer/plugins/webapi/ledgerstate" - manaAPI "github.com/iotaledger/goshimmer/plugins/webapi/mana" ) // ExplorerMessage defines the struct of the ExplorerMessage. @@ -139,7 +137,6 @@ type ExplorerOutput struct { Output *jsonmodels.Output `json:"output"` Metadata *jsonmodels.OutputMetadata `json:"metadata"` TxTimestamp int `json:"txTimestamp"` - PendingMana float64 `json:"pendingMana"` GradeOfFinality gof.GradeOfFinality `json:"gradeOfFinality"` } @@ -181,7 +178,6 @@ func setupExplorerRoutes(routeGroup *echo.Group) { routeGroup.GET("/output/:outputID", ledgerstateAPI.GetOutput) routeGroup.GET("/output/:outputID/metadata", ledgerstateAPI.GetOutputMetadata) routeGroup.GET("/output/:outputID/consumers", ledgerstateAPI.GetOutputConsumers) - routeGroup.GET("/mana/pending", manaAPI.GetPendingMana) routeGroup.GET("/branch/:branchID", ledgerstateAPI.GetBranch) routeGroup.GET("/branch/:branchID/children", ledgerstateAPI.GetBranchChildren) routeGroup.GET("/branch/:branchID/conflicts", ledgerstateAPI.GetBranchConflicts) @@ -266,9 +262,6 @@ func findAddress(strAddress string) (*ExplorerAddress, error) { } }) - // how much pending mana the output has? - pendingMana, _ := messagelayer.PendingManaOnOutput(output.ID()) - // obtain information about the consumer of the output being considered confirmedConsumerID := deps.Tangle.Utils.ConfirmedConsumer(output.ID()) @@ -277,7 +270,6 @@ func findAddress(strAddress string) (*ExplorerAddress, error) { Output: jsonmodels.NewOutput(output), Metadata: jsonmodels.NewOutputMetadata(metaData, confirmedConsumerID), TxTimestamp: int(timestamp), - PendingMana: pendingMana, GradeOfFinality: metaData.GradeOfFinality(), }) } diff --git a/plugins/manarefresher/delegation_receiver.go b/plugins/manarefresher/delegation_receiver.go deleted file mode 100644 index 9f654109cc..0000000000 --- a/plugins/manarefresher/delegation_receiver.go +++ /dev/null @@ -1,117 +0,0 @@ -package manarefresher - -import ( - "sync" - "time" - - "github.com/iotaledger/goshimmer/packages/clock" - "github.com/iotaledger/goshimmer/packages/ledger" - "github.com/iotaledger/goshimmer/packages/ledger/utxo" - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm/indexer" -) - -// DelegationReceiver checks for delegation outputs on the wallet address and keeps the most recent delegated balance. -type DelegationReceiver struct { - *wallet - delegatedFunds map[devnetvm.Color]uint64 - delFundsMutex sync.RWMutex - sync.RWMutex - - // utility to be able to filter based on the same timestamp - localTimeNow time.Time -} - -// Scan scans for unspent delegation outputs on the delegation receiver address. -func (d *DelegationReceiver) Scan() []*devnetvm.AliasOutput { - d.Lock() - defer d.Unlock() - - var outputs devnetvm.Outputs - deps.Indexer.CachedAddressOutputMappings(d.Address()).Consume(func(mapping *indexer.AddressOutputMapping) { - deps.Tangle.Ledger.Storage.CachedOutput(mapping.OutputID()).Consume(func(output utxo.Output) { - if typedOutput, ok := output.(devnetvm.Output); ok { - outputs = append(outputs, typedOutput) - } - }) - }) - // filterDelegationOutputs will use this time for condition checking - d.localTimeNow = clock.SyncedTime() - filtered := outputs.Filter(d.filterDelegationOutputs) - - scanResult := make([]*devnetvm.AliasOutput, len(filtered)) - for i, output := range filtered { - scanResult[i] = output.Clone().(*devnetvm.AliasOutput) - } - d.updateDelegatedFunds(scanResult) - return scanResult -} - -// updateDelegatedFunds updates the internal store of the delegated amount. -func (d *DelegationReceiver) updateDelegatedFunds(delegatedOutputs []*devnetvm.AliasOutput) { - d.delFundsMutex.Lock() - defer d.delFundsMutex.Unlock() - current := map[devnetvm.Color]uint64{} - for _, alias := range delegatedOutputs { - alias.Balances().ForEach(func(color devnetvm.Color, balance uint64) bool { - current[color] += balance - return true - }) - } - d.delegatedFunds = current -} - -// TotalDelegatedFunds returns the total amount of funds currently delegated to this node. -func (d *DelegationReceiver) TotalDelegatedFunds() uint64 { - d.delFundsMutex.RLock() - defer d.delFundsMutex.RUnlock() - total := uint64(0) - for _, balance := range d.delegatedFunds { - total += balance - } - return total -} - -// Address returns the receive address of the delegation receiver. -func (d *DelegationReceiver) Address() devnetvm.Address { - return d.address -} - -// filterDelegationOutputs checks if the output satisfies the conditions to be considered a valid delegation outputs -// that the plugin can refresh: -// - output is an AliasOutput -// - it is unspent -// - it is confirmed -// - its state address is the same as DelegationReceiver's address -// - output is delegated -// - if delegation time lock is present, it doesn't expire within 1 minute -func (d *DelegationReceiver) filterDelegationOutputs(output devnetvm.Output) bool { - // it has to be an alias - if output.Type() != devnetvm.AliasOutputType { - return false - } - // it has to be unspent - isUnspent := false - isConfirmed := false - deps.Tangle.Ledger.Storage.CachedOutputMetadata(output.ID()).Consume(func(outputMetadata *ledger.OutputMetadata) { - isUnspent = !outputMetadata.IsSpent() - isConfirmed = deps.Tangle.ConfirmationOracle.IsOutputConfirmed(output.ID()) - }) - if !isUnspent || !isConfirmed { - return false - } - // has to be a delegation alias that the delegation address owns for at least 1 min into the future - alias := output.(*devnetvm.AliasOutput) - if !alias.GetStateAddress().Equals(d.address) { - return false - } - if !alias.IsDelegated() { - return false - } - // when delegation timelock is present, we want to have 1 minute window to prepare the refresh tx, otherwise just drop it - // TODO: what is the optimal window? - if !alias.DelegationTimelock().IsZero() && !alias.DelegationTimeLockedNow(d.localTimeNow.Add(time.Minute)) { - return false - } - return true -} diff --git a/plugins/manarefresher/parameters.go b/plugins/manarefresher/parameters.go deleted file mode 100644 index c8636b4404..0000000000 --- a/plugins/manarefresher/parameters.go +++ /dev/null @@ -1,20 +0,0 @@ -package manarefresher - -import ( - "time" - - "github.com/iotaledger/hive.go/configuration" -) - -// ParametersDefinition contains the definition of the parameters used by the manaRefresher plugin. -type ParametersDefinition struct { - // RefreshInterval defines the interval for refreshing delegated mana. - RefreshInterval time.Duration `default:"25m" usage:"interval for refreshing delegated mana (minutes)"` -} - -// Parameters contains the configuration used by the manaRefresher plugin. -var Parameters = &ParametersDefinition{} - -func init() { - configuration.BindParameters(Parameters, "manaRefresher") -} diff --git a/plugins/manarefresher/plugin.go b/plugins/manarefresher/plugin.go deleted file mode 100644 index c96e89690b..0000000000 --- a/plugins/manarefresher/plugin.go +++ /dev/null @@ -1,112 +0,0 @@ -package manarefresher - -import ( - "context" - "fmt" - "time" - - "github.com/cockroachdb/errors" - "github.com/iotaledger/hive.go/autopeering/peer" - "github.com/iotaledger/hive.go/daemon" - "github.com/iotaledger/hive.go/node" - "go.uber.org/dig" - - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm/indexer" - "github.com/iotaledger/goshimmer/packages/shutdown" - "github.com/iotaledger/goshimmer/packages/tangle" -) - -var ( - // Plugin is the plugin instance of the manarefresher plugin. - Plugin *node.Plugin - deps = new(dependencies) - refresher *Refresher -) - -type dependencies struct { - dig.In - Local *peer.Local - Tangle *tangle.Tangle - Indexer *indexer.Indexer -} - -// minRefreshInterval is the minimum refresh interval allowed for delegated outputs. -const minRefreshInterval = 1 * time.Minute - -func init() { - Plugin = node.NewPlugin("ManaRefresher", deps, node.Enabled, configure, run) -} - -// configure events. -func configure(plugin *node.Plugin) { - plugin.LogInfof("starting node with manarefresher plugin") - nodeIDPrivateKey, err := deps.Local.Database().LocalPrivateKey() - if err != nil { - panic(errors.Wrap(err, "couldn't load private key of node identity")) - } - localWallet := newWalletFromPrivateKey(nodeIDPrivateKey) - refresher = NewRefresher(localWallet, &DelegationReceiver{wallet: localWallet}) - - if Parameters.RefreshInterval < minRefreshInterval { - panic(fmt.Sprintf("manarefresh interval of %d is too small, minimum is %d ", Parameters.RefreshInterval, minRefreshInterval)) - } -} - -func run(plugin *node.Plugin) { - if err := daemon.BackgroundWorker("ManaRefresher-plugin", func(ctx context.Context) { - ticker := time.NewTicker(Parameters.RefreshInterval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - - case <-ticker.C: - err := refresher.Refresh() - if err != nil { - plugin.LogErrorf("couldn't refresh mana: %w", err) - } - } - } - }, shutdown.PriorityManaRefresher); err != nil { - plugin.Panicf("Failed to start as daemon: %s", err) - } -} - -// DelegationAddress returns the current mana delegation address of the node. -func DelegationAddress() (devnetvm.Address, error) { - if refresher != nil { - return refresher.receiver.Address(), nil - } - return nil, errors.Errorf("manarefresher plugin is disabled") -} - -// TotalDelegatedFunds returns the amount of funds delegated to the node. -func TotalDelegatedFunds() (amount uint64) { - if refresher == nil { - return 0 - } - // need to scan to get the most recent - _ = refresher.receiver.Scan() - return refresher.receiver.TotalDelegatedFunds() -} - -// DelegatedOutputs returns all confirmed, unspent outputs that are delegated to the node. -func DelegatedOutputs() (delegated devnetvm.Outputs, err error) { - if refresher == nil { - err = errors.Errorf("manarefresher plugin is not running, node doesn't process delegated outputs") - return - } - // need to scan to get the most recent - found := refresher.receiver.Scan() - if len(found) == 0 { - err = errors.Errorf("no confirmed delegated outputs found") - return - } - delegated = make(devnetvm.Outputs, len(found)) - for i := range found { - delegated[i] = found[i] - } - return delegated, nil -} diff --git a/plugins/manarefresher/refresher.go b/plugins/manarefresher/refresher.go deleted file mode 100644 index 1f28f4ce82..0000000000 --- a/plugins/manarefresher/refresher.go +++ /dev/null @@ -1,108 +0,0 @@ -package manarefresher - -import ( - "context" - "time" - - "github.com/cockroachdb/errors" - - "github.com/iotaledger/goshimmer/packages/clock" - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" - "github.com/iotaledger/goshimmer/packages/tangle" - "github.com/iotaledger/goshimmer/plugins/messagelayer" -) - -// maxBookedAwaitTime is the time the refresher waits for an issued tx to become booked. -const maxBookedAwaitTime = 5 * time.Second - -// Refresher is a component that takes care of refreshing the mana delegated to the node. -type Refresher struct { - wallet *wallet - receiver *DelegationReceiver -} - -// NewRefresher creates a new Refresher object. -func NewRefresher(wallet *wallet, receiver *DelegationReceiver) *Refresher { - return &Refresher{ - wallet: wallet, - receiver: receiver, - } -} - -// Refresh scans the tangle for delegated outputs, and refreshes the node's mana by moving those. -func (r *Refresher) Refresh() (err error) { - delegationOutputs := r.receiver.Scan() - if len(delegationOutputs) == 0 { - return - } - numberOfChunks := len(delegationOutputs)/devnetvm.MaxInputCount + 1 - - for i := 0; i < numberOfChunks; i++ { - // which chunks to consume? - var consumedChunk []*devnetvm.AliasOutput - if len(delegationOutputs) > devnetvm.MaxInputCount { - consumedChunk = delegationOutputs[:devnetvm.MaxInputCount] - delegationOutputs = delegationOutputs[devnetvm.MaxInputCount:] - } else { - consumedChunk = delegationOutputs - } - - var tx *devnetvm.Transaction - tx, err = r.prepareRefreshingTransaction(consumedChunk) - if err != nil { - return - } - err = r.sendTransaction(tx) - if err != nil { - return - } - } - return nil -} - -// prepareRefreshingTransaction prepares a transaction moving delegated outputs with state transition only and pledging mana -// to the node itself. -func (r *Refresher) prepareRefreshingTransaction(toBeRefreshed []*devnetvm.AliasOutput) (tx *devnetvm.Transaction, err error) { - // prepare inputs - inputs := make(devnetvm.Inputs, len(toBeRefreshed)) - for k, output := range toBeRefreshed { - inputs[k] = output.Input() - } - // prepare outputs - outputs := make(devnetvm.Outputs, len(toBeRefreshed)) - for k, alias := range toBeRefreshed { - outputs[k] = alias.NewAliasOutputNext(false) - } - // prepare essence - essence := devnetvm.NewTransactionEssence( - 0, - clock.SyncedTime(), - deps.Local.ID(), // pledge both manas to self - deps.Local.ID(), - devnetvm.NewInputs(inputs...), - devnetvm.NewOutputs(outputs...), - ) - tx = devnetvm.NewTransaction(essence, r.wallet.unlockBlocks(essence)) - - // check transaction validity - if transactionErr := deps.Tangle.Ledger.CheckTransaction(context.Background(), tx); transactionErr != nil { - return nil, transactionErr - } - - // check if transaction is too old - if tx.Essence().Timestamp().Before(clock.SyncedTime().Add(-tangle.MaxReattachmentTimeMin)) { - return nil, errors.Errorf("transaction timestamp is older than MaxReattachmentTime (%s) and cannot be issued", tangle.MaxReattachmentTimeMin) - } - - return tx, nil -} - -func (r *Refresher) sendTransaction(tx *devnetvm.Transaction) (err error) { - issueTransaction := func() (*tangle.Message, error) { - return deps.Tangle.IssuePayload(tx) - } - if _, err = messagelayer.AwaitMessageToBeBooked(issueTransaction, tx.ID(), maxBookedAwaitTime); err != nil { - return err - } - return nil -} diff --git a/plugins/manarefresher/wallet.go b/plugins/manarefresher/wallet.go deleted file mode 100644 index 57a84dc45c..0000000000 --- a/plugins/manarefresher/wallet.go +++ /dev/null @@ -1,51 +0,0 @@ -package manarefresher - -import ( - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/generics/lo" - - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" -) - -// simple wallet with 1 keypair (there is only one address). -type wallet struct { - keyPair ed25519.KeyPair - address *devnetvm.ED25519Address -} - -// newWalletFromPrivateKey generates a simple wallet with one address. -func newWalletFromPrivateKey(pk ed25519.PrivateKey) *wallet { - return &wallet{ - keyPair: ed25519.KeyPair{ - PrivateKey: pk, - PublicKey: pk.Public(), - }, - address: devnetvm.NewED25519Address(pk.Public()), - } -} - -func (w *wallet) privateKey() ed25519.PrivateKey { - return w.keyPair.PrivateKey -} - -func (w *wallet) publicKey() ed25519.PublicKey { - return w.keyPair.PublicKey -} - -func (w *wallet) sign(txEssence *devnetvm.TransactionEssence) *devnetvm.ED25519Signature { - return devnetvm.NewED25519Signature(w.publicKey(), w.privateKey().Sign(lo.PanicOnErr(txEssence.Bytes()))) -} - -// unlockBlocks returns the unlock blocks assuming all inputs can be unlocked by the same signature. -func (w *wallet) unlockBlocks(txEssence *devnetvm.TransactionEssence) []devnetvm.UnlockBlock { - signatureUnlockBlock := devnetvm.NewSignatureUnlockBlock(w.sign(txEssence)) - unlockBlocks := make([]devnetvm.UnlockBlock, len(txEssence.Inputs())) - unlockBlocks[0] = signatureUnlockBlock - for i := range txEssence.Inputs() { - if i == 0 { - continue - } - unlockBlocks[i] = devnetvm.NewReferenceUnlockBlock(0) - } - return unlockBlocks -} diff --git a/plugins/messagelayer/mana_plugin.go b/plugins/messagelayer/mana_plugin.go index 8cd0377d6b..b3b3fb7dab 100644 --- a/plugins/messagelayer/mana_plugin.go +++ b/plugins/messagelayer/mana_plugin.go @@ -3,7 +3,6 @@ package messagelayer import ( "context" "fmt" - "math" "sort" "time" @@ -69,8 +68,8 @@ func configureManaPlugin(*node.Plugin) { allowedPledgeNodes = make(map[mana.Type]AllowedPledge) baseManaVectors = make(map[mana.Type]mana.BaseManaVector) - baseManaVectors[mana.AccessMana], _ = mana.NewBaseManaVector(mana.AccessMana) - baseManaVectors[mana.ConsensusMana], _ = mana.NewBaseManaVector(mana.ConsensusMana) + baseManaVectors[mana.AccessMana] = mana.NewBaseManaVector() + baseManaVectors[mana.ConsensusMana] = mana.NewBaseManaVector() // configure storage for each vector type storages = make(map[mana.Type]*objectstorage.ObjectStorage[*mana.PersistableBaseMana]) @@ -180,13 +179,9 @@ func gatherInputInfos(transaction *devnetvm.Transaction) (totalAmount float64, i func runManaPlugin(_ *node.Plugin) { // mana calculation coefficients can be set from config - ema1 := ManaParameters.EmaCoefficient1 - ema2 := ManaParameters.EmaCoefficient2 - dec := ManaParameters.Decay pruneInterval := ManaParameters.PruneConsensusEventLogsInterval vectorsCleanUpInterval := ManaParameters.VectorsCleanupInterval fmt.Printf("Prune interval: %v\n", pruneInterval) - mana.SetCoefficients(ema1, ema2, dec) if err := daemon.BackgroundWorker("Mana", func(ctx context.Context) { defer manaLogger.Infof("Stopping %s ... done", PluginName) // ticker := time.NewTicker(pruneInterval) @@ -305,7 +300,7 @@ func GetManaMap(manaType mana.Type, optionalUpdateTime ...time.Time) (mana.NodeM if !QueryAllowed() { return mana.NodeMap{}, time.Now(), ErrQueryNotAllowed } - return baseManaVectors[manaType].GetManaMap(optionalUpdateTime...) + return baseManaVectors[manaType].GetManaMap() } // GetCMana is a wrapper for the approval weight. @@ -322,7 +317,7 @@ func GetTotalMana(manaType mana.Type, optionalUpdateTime ...time.Time) (float64, if !QueryAllowed() { return 0, time.Now(), ErrQueryNotAllowed } - manaMap, updateTime, err := baseManaVectors[manaType].GetManaMap(optionalUpdateTime...) + manaMap, updateTime, err := baseManaVectors[manaType].GetManaMap() if err != nil { return 0, time.Now(), err } @@ -339,7 +334,7 @@ func GetAccessMana(nodeID identity.ID, optionalUpdateTime ...time.Time) (float64 if !QueryAllowed() { return 0, time.Now(), ErrQueryNotAllowed } - return baseManaVectors[mana.AccessMana].GetMana(nodeID, optionalUpdateTime...) + return baseManaVectors[mana.AccessMana].GetMana(nodeID) } // GetConsensusMana returns the consensus mana of the node specified. @@ -347,7 +342,7 @@ func GetConsensusMana(nodeID identity.ID, optionalUpdateTime ...time.Time) (floa if !QueryAllowed() { return 0, time.Now(), ErrQueryNotAllowed } - return baseManaVectors[mana.ConsensusMana].GetMana(nodeID, optionalUpdateTime...) + return baseManaVectors[mana.ConsensusMana].GetMana(nodeID) } // GetNeighborsMana returns the type mana of the nodes neighbors. @@ -359,7 +354,7 @@ func GetNeighborsMana(manaType mana.Type, neighbors []*gossip.Neighbor, optional res := make(mana.NodeMap) for _, n := range neighbors { // in case of error, value is 0.0 - value, _, _ := baseManaVectors[manaType].GetMana(n.ID(), optionalUpdateTime...) + value, _, _ := baseManaVectors[manaType].GetMana(n.ID()) res[n.ID()] = value } return res, nil @@ -377,12 +372,6 @@ func GetAllManaMaps(optionalUpdateTime ...time.Time) (map[mana.Type]mana.NodeMap return res, nil } -// OverrideMana sets the nodes mana to a specific value. -// It can be useful for debugging, setting faucet mana, initialization, etc.. Triggers ManaUpdated. -func OverrideMana(manaType mana.Type, nodeID identity.ID, bm *mana.AccessBaseMana) { - baseManaVectors[manaType].SetMana(nodeID, bm) -} - // GetAllowedPledgeNodes returns the list of nodes that type mana is allowed to be pledged to. func GetAllowedPledgeNodes(manaType mana.Type) AllowedPledge { return allowedPledgeNodes[manaType] @@ -458,42 +447,6 @@ func verifyPledgeNodes() error { return nil } -// PendingManaOnOutput predicts how much mana (bm2) will be pledged to a node if the output specified is spent. -func PendingManaOnOutput(outputID utxo.OutputID) (float64, time.Time) { - cachedOutputMetadata := deps.Tangle.Ledger.Storage.CachedOutputMetadata(outputID) - defer cachedOutputMetadata.Release() - outputMetadata, exists := cachedOutputMetadata.Unwrap() - - // spent output has 0 pending mana. - if !exists || outputMetadata.IsSpent() { - return 0, time.Time{} - } - - var value float64 - deps.Tangle.Ledger.Storage.CachedOutput(outputID).Consume(func(output utxo.Output) { - outputEssence := output.(devnetvm.Output) - outputEssence.Balances().ForEach(func(color devnetvm.Color, balance uint64) bool { - value += float64(balance) - return true - }) - }) - - var txTimestamp time.Time - deps.Tangle.Ledger.Storage.CachedOutput(outputID).Consume(func(output utxo.Output) { - cachedTx := deps.Tangle.Ledger.Storage.CachedTransaction(output.ID().TransactionID) - defer cachedTx.Release() - tx, _ := cachedTx.Unwrap() - txTimestamp = tx.(*devnetvm.Transaction).Essence().Timestamp() - }) - - return GetPendingMana(value, time.Since(txTimestamp)), txTimestamp -} - -// GetPendingMana returns the mana pledged by spending a `value` output that sat for `n` duration. -func GetPendingMana(value float64, n time.Duration) float64 { - return value * (1 - math.Pow(math.E, -mana.Decay*(n.Seconds()))) -} - // // GetLoggedEvents gets the events logs for the node IDs and time frame specified. If none is specified, it returns the logs for all nodes. // func GetLoggedEvents(identityIDs []identity.ID, startTime time.Time, endTime time.Time) (map[identity.ID]*EventsLogs, error) { // logs := make(map[identity.ID]*EventsLogs) diff --git a/plugins/messagelayer/parameters.go b/plugins/messagelayer/parameters.go index 3d3e79b83e..32f1f13fcb 100644 --- a/plugins/messagelayer/parameters.go +++ b/plugins/messagelayer/parameters.go @@ -29,12 +29,6 @@ type ParametersDefinition struct { // ManaParametersDefinition contains the definition of the parameters used by the mana plugin. type ManaParametersDefinition struct { - // EmaCoefficient1 defines the coefficient used for Effective Base Mana 1 (moving average) calculation. - EmaCoefficient1 float64 `default:"0.00003209" usage:"coefficient used for Effective Base Mana 1 (moving average) calculation"` - // EmaCoefficient2 defines the coefficient used for Effective Base Mana 2 (moving average) calculation. - EmaCoefficient2 float64 `default:"0.0057762265" usage:"coefficient used for Effective Base Mana 1 (moving average) calculation"` - // Decay defines the decay coefficient used for Base Mana 2 calculation. - Decay float64 `default:"0.00003209" usage:"decay coefficient used for Base Mana 2 calculation"` // AllowedAccessPledge defines the list of nodes that access mana is allowed to be pledged to. AllowedAccessPledge []string `usage:"list of nodes that access mana is allowed to be pledged to"` // AllowedAccessFilterEnabled defines if access mana pledge filter is enabled. diff --git a/plugins/metrics/mana.go b/plugins/metrics/mana.go index 5984a5989f..dbfad22269 100644 --- a/plugins/metrics/mana.go +++ b/plugins/metrics/mana.go @@ -7,7 +7,6 @@ import ( "go.uber.org/atomic" "github.com/iotaledger/goshimmer/packages/mana" - "github.com/iotaledger/goshimmer/plugins/manarefresher" manaPlugin "github.com/iotaledger/goshimmer/plugins/messagelayer" ) @@ -69,9 +68,6 @@ var ( averageNeighborsAccess atomic.Float64 averageNeighborsConsensus atomic.Float64 - // internal metrics for delegated mana. - delegationAmount atomic.Uint64 - // internal metrics for pledges. pledges = NodePledgeMap{} pledgesLock sync.RWMutex @@ -148,11 +144,6 @@ func AveragePledgeAccess() mana.NodeMap { return result } -// DelegatedMana returns how much mana is currently delegated to the node. -func DelegatedMana() uint64 { - return delegationAmount.Load() -} - // addPledge populates the pledge logs for the node. func addPledge(event *mana.PledgedEvent) { pledgesLock.Lock() @@ -202,6 +193,4 @@ func measureMana() { consensusAvg = consensusSum / float64(len(neighborConsensusMap)) } averageNeighborsConsensus.Store(consensusAvg) - - delegationAmount.Store(manarefresher.TotalDelegatedFunds()) } diff --git a/plugins/prometheus/mana.go b/plugins/prometheus/mana.go index e109befaf5..d72d8e3219 100644 --- a/plugins/prometheus/mana.go +++ b/plugins/prometheus/mana.go @@ -125,6 +125,4 @@ func collectManaMetrics() { for nodeID, value := range consensusPledges { averageConsensusPledge.WithLabelValues(nodeID.String(), "bm1").Set(value) } - - delegatedMana.Set(float64(metrics.DelegatedMana())) } diff --git a/plugins/webapi/info/plugin.go b/plugins/webapi/info/plugin.go index 9f2909b911..5d28a9b37c 100644 --- a/plugins/webapi/info/plugin.go +++ b/plugins/webapi/info/plugin.go @@ -12,11 +12,9 @@ import ( "go.uber.org/dig" "github.com/iotaledger/goshimmer/packages/jsonmodels" - "github.com/iotaledger/goshimmer/packages/mana" "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/autopeering/discovery" "github.com/iotaledger/goshimmer/plugins/banner" - "github.com/iotaledger/goshimmer/plugins/manarefresher" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/metrics" ) @@ -115,12 +113,6 @@ func getInfo(c echo.Context) error { ConsensusTimestamp: tConsensus, } - var delegationAddressString string - delegationAddress, err := manarefresher.DelegationAddress() - if err == nil { - delegationAddressString = delegationAddress.Base58() - } - nodeQueueSizes := make(map[string]int) for nodeID, size := range deps.Tangle.Scheduler.NodeQueueSizes() { nodeQueueSizes[nodeID.String()] = size @@ -138,11 +130,9 @@ func getInfo(c echo.Context) error { metrics.MessageCountSinceStartPerComponentGrafana()[metrics.Solidifier]), TotalMessageCount: int(metrics.InitialMessageCountPerComponentGrafana()[metrics.Store] + metrics.MessageCountSinceStartPerComponentGrafana()[metrics.Store]), - EnabledPlugins: enabledPlugins, - DisabledPlugins: disabledPlugins, - Mana: nodeMana, - ManaDelegationAddress: delegationAddressString, - ManaDecay: mana.Decay, + EnabledPlugins: enabledPlugins, + DisabledPlugins: disabledPlugins, + Mana: nodeMana, Scheduler: jsonmodels.Scheduler{ Running: deps.Tangle.Scheduler.Running(), Rate: deps.Tangle.Scheduler.Rate().String(), diff --git a/plugins/webapi/mana/delegated.go b/plugins/webapi/mana/delegated.go deleted file mode 100644 index 462dca628a..0000000000 --- a/plugins/webapi/mana/delegated.go +++ /dev/null @@ -1,48 +0,0 @@ -package mana - -import ( - "net/http" - - "github.com/labstack/echo" - - "github.com/iotaledger/goshimmer/packages/jsonmodels" - "github.com/iotaledger/goshimmer/plugins/manarefresher" -) - -// region GetDelegatedMana ///////////////////////////////////////////////////////////////////////////////////////////// - -// GetDelegatedMana handles the GetDelegatedMana request. -func GetDelegatedMana(c echo.Context) error { - delegatedMana := manarefresher.TotalDelegatedFunds() - return c.JSON(http.StatusOK, &GetDelegatedManaResponse{DelegatedMana: delegatedMana}) -} - -// GetDelegatedManaResponse is the response struct for the GetDelegatedMana endpoint. -type GetDelegatedManaResponse struct { - DelegatedMana uint64 `json:"delegatedMana"` -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// GetDelegatedOutputs ///////////////////////////////////////////////////////////////////////////////////////////////// - -// GetDelegatedOutputs handles the GetDelegatedOutputs requests. -func GetDelegatedOutputs(c echo.Context) error { - outputs, err := manarefresher.DelegatedOutputs() - if err != nil { - return c.JSON(http.StatusNotFound, &GetDelegatedOutputsResponse{Error: err.Error()}) - } - delegatedOutputsJSON := make([]*jsonmodels.Output, len(outputs)) - for i, o := range outputs { - delegatedOutputsJSON[i] = jsonmodels.NewOutput(o) - } - return c.JSON(http.StatusOK, &GetDelegatedOutputsResponse{Outputs: delegatedOutputsJSON}) -} - -// GetDelegatedOutputsResponse is the response struct for the GetDelegatedOutputs endpoint. -type GetDelegatedOutputsResponse struct { - Outputs []*jsonmodels.Output `json:"delegatedOutputs"` - Error string `json:"error,omitempty"` -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/webapi/mana/pending.go b/plugins/webapi/mana/pending.go deleted file mode 100644 index 47a770fe3b..0000000000 --- a/plugins/webapi/mana/pending.go +++ /dev/null @@ -1,29 +0,0 @@ -package mana - -import ( - "net/http" - - "github.com/labstack/echo" - - "github.com/iotaledger/goshimmer/packages/jsonmodels" - "github.com/iotaledger/goshimmer/packages/ledger/utxo" - manaPlugin "github.com/iotaledger/goshimmer/plugins/messagelayer" -) - -// GetPendingMana handles the request. -func GetPendingMana(c echo.Context) error { - var req jsonmodels.PendingRequest - if err := c.Bind(&req); err != nil { - return c.JSON(http.StatusBadRequest, jsonmodels.PendingResponse{Error: err.Error()}) - } - var outputID utxo.OutputID - if err := outputID.FromBase58(req.OutputID); err != nil { - return c.JSON(http.StatusBadRequest, jsonmodels.PendingResponse{Error: err.Error()}) - } - pending, t := manaPlugin.PendingManaOnOutput(outputID) - return c.JSON(http.StatusOK, jsonmodels.PendingResponse{ - Mana: pending, - OutputID: outputID.Base58(), - Timestamp: t.Unix(), - }) -} diff --git a/plugins/webapi/mana/plugin.go b/plugins/webapi/mana/plugin.go index a0e40b0365..3712c5ede1 100644 --- a/plugins/webapi/mana/plugin.go +++ b/plugins/webapi/mana/plugin.go @@ -35,10 +35,7 @@ func configure(_ *node.Plugin) { deps.Server.GET("/mana/percentile", getPercentileHandler) deps.Server.GET("/mana/access/online", getOnlineAccessHandler) deps.Server.GET("/mana/consensus/online", getOnlineConsensusHandler) - deps.Server.GET("/mana/pending", GetPendingMana) deps.Server.GET("mana/allowedManaPledge", allowedManaPledgeHandler) - deps.Server.GET("mana/delegated", GetDelegatedMana) - deps.Server.GET("mana/delegated/outputs", GetDelegatedOutputs) // deps.Server.GET("/mana/consensus/past", getPastConsensusManaVectorHandler) // deps.Server.GET("/mana/consensus/logs", getEventLogsHandler) // deps.Server.GET("/mana/consensus/metadata", getPastConsensusVectorMetadataHandler) diff --git a/tools/cli-wallet/delegate_funds.go b/tools/cli-wallet/delegate_funds.go deleted file mode 100644 index faf8fc3c11..0000000000 --- a/tools/cli-wallet/delegate_funds.go +++ /dev/null @@ -1,129 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "os" - "time" - - "github.com/mr-tron/base58" - - "github.com/iotaledger/goshimmer/client/wallet" - "github.com/iotaledger/goshimmer/client/wallet/packages/address" - "github.com/iotaledger/goshimmer/client/wallet/packages/delegateoptions" - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" -) - -func execDelegateFundsCommand(command *flag.FlagSet, cliWallet *wallet.Wallet) { - command.Usage = func() { - printUsage(command) - } - - helpPtr := command.Bool("help", false, "show this help screen") - amountPtr := command.Int64("amount", 0, "the amount of tokens that should be delegated") - colorPtr := command.String("color", "IOTA", "color of the tokens that should delegated") - delegationAddressPtr := command.String("del-addr", "", "address to delegate funds to. when omitted, wallet delegates to the node it is connected to") - timelockUntilPtr := command.Int64("until", 0, "unix timestamp until which the delegated funds are timelocked") - accessManaPledgeIDPtr := command.String("access-mana-id", "", "node ID to pledge access mana to") - consensusManaPledgeIDPtr := command.String("consensus-mana-id", "", "node ID to pledge consensus mana to") - - err := command.Parse(os.Args[2:]) - if err != nil { - panic(err) - } - - if *helpPtr { - printUsage(command) - } - if *amountPtr < int64(devnetvm.DustThresholdAliasOutputIOTA) { - printUsage(command, fmt.Sprintf("delegation amount must be greater than %d", devnetvm.DustThresholdAliasOutputIOTA)) - } - if *colorPtr == "" { - printUsage(command, "color must be set") - } - var delegationAddress devnetvm.Address - delegateToConnectedNode := false - var status wallet.ServerStatus - if *delegationAddressPtr == "" { - var statusErr error - status, statusErr = cliWallet.ServerStatus() - if statusErr != nil { - printUsage(command, fmt.Sprintf("failed to get delegation address from connected node: %s", statusErr.Error())) - } - delegationAddress, err = devnetvm.AddressFromBase58EncodedString(status.DelegationAddress) - if err != nil { - printUsage(command, fmt.Sprintf("failed to parse connected node's delegation adddress: %s", err.Error())) - } - delegateToConnectedNode = true - } else { - delegationAddress, err = devnetvm.AddressFromBase58EncodedString(*delegationAddressPtr) - if err != nil { - printUsage(command, fmt.Sprintf("provided delelegation address %s is not a valid IOTA address: %s", *delegationAddressPtr, err.Error())) - } - } - - var fundsColor devnetvm.Color - if *amountPtr >= int64(devnetvm.DustThresholdAliasOutputIOTA) { - // get color - switch *colorPtr { - case "IOTA": - fundsColor = devnetvm.ColorIOTA - case "NEW": - fundsColor = devnetvm.ColorMint - default: - colorBytes, parseErr := base58.Decode(*colorPtr) - if parseErr != nil { - printUsage(command, parseErr.Error()) - } - - fundsColor, _, parseErr = devnetvm.ColorFromBytes(colorBytes) - if parseErr != nil { - printUsage(command, parseErr.Error()) - } - } - } - - options := []delegateoptions.DelegateFundsOption{ - delegateoptions.AccessManaPledgeID(*accessManaPledgeIDPtr), - delegateoptions.ConsensusManaPledgeID(*consensusManaPledgeIDPtr), - } - - if fundsColor == devnetvm.ColorIOTA { - // when we are delegating IOTA, we automatically fulfill the minimum dust requirement of the alias - options = append(options, delegateoptions.Destination( - address.Address{AddressBytes: delegationAddress.Array()}, map[devnetvm.Color]uint64{ - fundsColor: uint64(*amountPtr), - })) - } else { - // when we are delegating anything else, we need IOTAs - options = append(options, delegateoptions.Destination( - address.Address{AddressBytes: delegationAddress.Array()}, map[devnetvm.Color]uint64{ - devnetvm.ColorIOTA: devnetvm.DustThresholdAliasOutputIOTA, - fundsColor: uint64(*amountPtr), - })) - } - - if *timelockUntilPtr != 0 { - if time.Now().Unix() > *timelockUntilPtr { - printUsage(command, fmt.Sprintf("delegation timelock %s is in the past. now is: %s", time.Unix(*timelockUntilPtr, 0).String(), time.Unix(time.Now().Unix(), 0).String())) - } else { - options = append(options, delegateoptions.DelegateUntil(time.Unix(*timelockUntilPtr, 0))) - } - } - fmt.Println("Delegating funds...") - _, delegationIDs, err := cliWallet.DelegateFunds(options...) - if err != nil { - printUsage(command, err.Error()) - } - - fmt.Println() - if delegateToConnectedNode { - fmt.Printf("\nDelegating to node %s, delegation address %s\n", status.ID, delegationAddress.Base58()) - } else { - fmt.Printf("\nDelegating to address %s\n", delegationAddress.Base58()) - } - for _, id := range delegationIDs { - fmt.Println("Delegation ID is: ", id.Base58()) - } - fmt.Println("Delegating funds... [DONE]") -} diff --git a/tools/cli-wallet/main.go b/tools/cli-wallet/main.go index 6ce61d4c09..db4bd1f437 100644 --- a/tools/cli-wallet/main.go +++ b/tools/cli-wallet/main.go @@ -64,8 +64,6 @@ func main() { claimConditionalFundsCommand := flag.NewFlagSet("claim-conditional", flag.ExitOnError) createAssetCommand := flag.NewFlagSet("create-asset", flag.ExitOnError) assetInfoCommand := flag.NewFlagSet("asset-info", flag.ExitOnError) - delegateFundsCommand := flag.NewFlagSet("delegate-funds", flag.ExitOnError) - reclaimDelegatedFundsCommand := flag.NewFlagSet("reclaim-delegated", flag.ExitOnError) createNFTCommand := flag.NewFlagSet("create-nft", flag.ExitOnError) transferNFTCommand := flag.NewFlagSet("transfer-nft", flag.ExitOnError) destroyNFTCommand := flag.NewFlagSet("destroy-nft", flag.ExitOnError) @@ -95,10 +93,6 @@ func main() { execCreateAssetCommand(createAssetCommand, wallet) case "asset-info": execAssetInfoCommand(assetInfoCommand, wallet) - case "delegate-funds": - execDelegateFundsCommand(delegateFundsCommand, wallet) - case "reclaim-delegated": - execReclaimDelegatedFundsCommand(reclaimDelegatedFundsCommand, wallet) case "create-nft": execCreateNFTCommand(createNFTCommand, wallet) case "transfer-nft": diff --git a/tools/cli-wallet/pendingmana.go b/tools/cli-wallet/pendingmana.go index 1fbe753de0..81b1a1f94f 100644 --- a/tools/cli-wallet/pendingmana.go +++ b/tools/cli-wallet/pendingmana.go @@ -3,9 +3,7 @@ package main import ( "flag" "fmt" - "math" "os" - "time" "github.com/iotaledger/goshimmer/client/wallet" "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" @@ -17,11 +15,6 @@ func execPendingMana(command *flag.FlagSet, cliWallet *wallet.Wallet) { printUsage(nil, err.Error()) } - status, err := cliWallet.ServerStatus() - if err != nil { - printUsage(nil, err.Error()) - } - fmt.Println("\nPending Mana for all unspent outputs") fmt.Println("-----------------------------------") unspentOutputs := cliWallet.UnspentOutputs() @@ -33,13 +26,8 @@ func execPendingMana(command *flag.FlagSet, cliWallet *wallet.Wallet) { total += float64(balance) return true }) - pendingMana := getPendingMana(total, time.Since(output.Metadata.Timestamp), status.ManaDecay) - fmt.Printf("\tOutputID: %s - Pending Mana: %f\n", ID.Base58(), pendingMana) + fmt.Printf("\tOutputID: %s - Pending Mana: %f\n", ID.Base58(), total) } } fmt.Println() -} - -func getPendingMana(value float64, n time.Duration, decay float64) float64 { - return value * (1 - math.Pow(math.E, -decay*(n.Seconds()))) -} +} \ No newline at end of file diff --git a/tools/cli-wallet/reclaim_delegated.go b/tools/cli-wallet/reclaim_delegated.go deleted file mode 100644 index 0428517fb5..0000000000 --- a/tools/cli-wallet/reclaim_delegated.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "os" - - "github.com/iotaledger/goshimmer/client/wallet" - "github.com/iotaledger/goshimmer/client/wallet/packages/reclaimoptions" - "github.com/iotaledger/goshimmer/packages/ledger/vm/devnetvm" -) - -func execReclaimDelegatedFundsCommand(command *flag.FlagSet, cliWallet *wallet.Wallet) { - command.Usage = func() { - printUsage(command) - } - - helpPtr := command.Bool("help", false, "show this help screen") - delegationIDPtr := command.String("id", "", "delegation ID that should be reclaimed") - toAddressPtr := command.String("to-addr", "", "optional address where to send reclaimed funds, wallet receive address by default") - accessManaPledgeIDPtr := command.String("access-mana-id", "", "node ID to pledge access mana to") - consensusManaPledgeIDPtr := command.String("consensus-mana-id", "", "node ID to pledge consensus mana to") - - err := command.Parse(os.Args[2:]) - if err != nil { - panic(err) - } - - if *helpPtr { - printUsage(command) - } - if *delegationIDPtr == "" { - printUsage(command, "delegation ID must be given") - } - - var toAddress devnetvm.Address - if *toAddressPtr != "" { - toAddress, err = devnetvm.AddressFromBase58EncodedString(*toAddressPtr) - if err != nil { - printUsage(command, fmt.Sprintf("wrong optional toAddress provided: %s", err.Error())) - } - } - - delegationID, err := devnetvm.AliasAddressFromBase58EncodedString(*delegationIDPtr) - if err != nil { - printUsage(command, fmt.Sprintf("%s is not a valid IOTA alias address: %s", *delegationIDPtr, err.Error())) - } - - options := []reclaimoptions.ReclaimFundsOption{ - reclaimoptions.Alias(delegationID.Base58()), - reclaimoptions.AccessManaPledgeID(*accessManaPledgeIDPtr), - reclaimoptions.ConsensusManaPledgeID(*consensusManaPledgeIDPtr), - } - - if toAddress != nil { - options = append(options, reclaimoptions.ToAddress(toAddress.Base58())) - } - fmt.Println("Reclaiming delegated fund...") - _, err = cliWallet.ReclaimDelegatedFunds(options...) - - if err != nil { - printUsage(command, err.Error()) - } - - fmt.Println() - fmt.Println("Reclaimed delegation ID is: ", delegationID.Base58()) - fmt.Println("Reclaiming delegated fund... [DONE]") -} diff --git a/tools/cli-wallet/serverstatus.go b/tools/cli-wallet/serverstatus.go index 08aa2b2d5f..573ef0f88c 100644 --- a/tools/cli-wallet/serverstatus.go +++ b/tools/cli-wallet/serverstatus.go @@ -24,5 +24,4 @@ func execServerStatusCommand(command *flag.FlagSet, cliWallet *wallet.Wallet) { fmt.Println("Server ID: ", status.ID) fmt.Println("Server Synced: ", status.Synced) fmt.Println("Server Version: ", status.Version) - fmt.Println("Delegation Address: ", status.DelegationAddress) } diff --git a/tools/docker-network/docker-compose.yml b/tools/docker-network/docker-compose.yml index d44ab24b57..94f827c1c0 100644 --- a/tools/docker-network/docker-compose.yml +++ b/tools/docker-network/docker-compose.yml @@ -19,7 +19,6 @@ services: --database.directory=/app/mainnetdb --node.peerDBDirectory=/app/peerdb --mana.enableResearchVectors=false - --mana.snapshotResetTime=true --messageLayer.snapshot.file=/run/secrets/goshimmer.message.snapshot.bin --messageLayer.snapshot.genesisNode= --messageLayer.startSynced=true @@ -59,7 +58,6 @@ services: --messageLayer.snapshot.genesisNode= --messageLayer.startSynced=true --node.disablePlugins=portcheck,clock,Firewall - --mana.snapshotResetTime=true deploy: replicas: ${GOSHIMMER_PEER_REPLICAS:-1} secrets: @@ -84,7 +82,6 @@ services: --node.disablePlugins=portcheck,clock,Firewall --prometheus.bindAddress=0.0.0.0:9311 --prometheus.processMetrics=false - --mana.snapshotResetTime=true --messageLayer.startSynced=true secrets: - goshimmer.config.json @@ -115,7 +112,6 @@ services: --faucet.seed=7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih --messageLayer.snapshot.genesisNode= --node.disablePlugins=portcheck,clock,Firewall - --mana.snapshotResetTime=true secrets: - goshimmer.config.json - goshimmer.message.snapshot.bin diff --git a/tools/integration-tests/tester/framework/parameters.go b/tools/integration-tests/tester/framework/parameters.go index 48cc025f06..79860bee93 100644 --- a/tools/integration-tests/tester/framework/parameters.go +++ b/tools/integration-tests/tester/framework/parameters.go @@ -108,7 +108,7 @@ func EntryNodeConfig() config.GoShimmer { c := PeerConfig() c.DisabledPlugins = append(c.DisabledPlugins, "issuer", "metrics", "valuetransfers", "consensus", - "manarefresher", "manualpeering", "chat", "WebAPIDataEndpoint", "WebAPIFaucetEndpoint", "WebAPIMessageEndpoint", + "manualpeering", "chat", "WebAPIDataEndpoint", "WebAPIFaucetEndpoint", "WebAPIMessageEndpoint", "Snapshot", "WebAPIWeightProviderEndpoint", "WebAPIInfoEndpoint", "WebAPILedgerstateEndpoint", "Firewall", "remotelog", "remotelogmetrics", "DAGsVisualizer") c.Gossip.Enabled = false diff --git a/tools/integration-tests/tester/tests/mana/mana_test.go b/tools/integration-tests/tester/tests/mana/mana_test.go index 024f94a246..9050d8286b 100644 --- a/tools/integration-tests/tester/tests/mana/mana_test.go +++ b/tools/integration-tests/tester/tests/mana/mana_test.go @@ -8,7 +8,6 @@ import ( "github.com/iotaledger/hive.go/identity" "github.com/mr-tron/base58" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/iotaledger/goshimmer/client" @@ -225,7 +224,7 @@ func TestManaApis(t *testing.T) { require.NoError(t, err) t.Logf("/mana/percentile %+v", resp) require.Equal(t, fullID(peers[0].ID()), resp.NodeID) - require.InDelta(t, 75.0, resp.Access, 0.01) + require.InDelta(t, 20.0, resp.Access, 0.01) resp, err = faucet.GetManaPercentile(faucet.ID().EncodeBase58()) require.NoError(t, err) @@ -237,22 +236,24 @@ func TestManaApis(t *testing.T) { // Test /mana/access/online and /mana/consensus/online t.Run("mana/*/online", func(t *testing.T) { // genesis node is not online - expectedOnlineAccessOrder := []string{peers[0].ID().String(), peers[1].ID().String(), peers[2].ID().String(), peers[3].ID().String()} - aResp, err := faucet.GetOnlineAccessMana() + aResp, err := peers[0].GoShimmerAPI.GetOnlineAccessMana() require.NoError(t, err) t.Logf("/mana/access/online %+v", aResp) - require.Len(t, aResp.Online, len(expectedOnlineAccessOrder)) - require.Equal(t, expectedOnlineAccessOrder[0], aResp.Online[0].ShortID) - unorderedOnlineNodes := aResp.Online[1:] - for j := range unorderedOnlineNodes { - assert.Contains(t, expectedOnlineAccessOrder[1:], unorderedOnlineNodes[j].ShortID) + require.Len(t, aResp.Online, len(n.Peers())) + nodeIDs := make([]string, len(aResp.Online)) + for i := range aResp.Online { + nodeIDs[i] = aResp.Online[i].ID + } + require.Len(t, nodeIDs, len(n.Peers())) + for _, peer := range n.Peers() { + require.Contains(t, nodeIDs, peer.ID().EncodeBase58()) } cResp, err := peers[0].GoShimmerAPI.GetOnlineConsensusMana() require.NoError(t, err) t.Logf("/mana/consensus/online %+v", cResp) require.Len(t, cResp.Online, len(n.Peers())) - nodeIDs := make([]string, len(cResp.Online)) + nodeIDs = make([]string, len(cResp.Online)) for i := range cResp.Online { nodeIDs[i] = cResp.Online[i].ID } @@ -262,18 +263,6 @@ func TestManaApis(t *testing.T) { } }) - // Test /mana/pending - t.Run("mana/pending", func(t *testing.T) { - unspentOutputs, err := peers[1].PostAddressUnspentOutputs([]string{peers[1].Address(0).Base58()}) - require.NoError(t, err) - outputID := unspentOutputs.UnspentOutputs[0].Outputs[0].Output.OutputID.Base58 - resp, err := peers[1].GetPending(outputID) - require.NoError(t, err) - t.Logf("/mana/pending %+v", resp) - require.Equal(t, outputID, resp.OutputID) - require.Greater(t, resp.Mana, minConsensusMana) - }) - // Test /mana/allowedManaPledge t.Run("mana/allowedManaPledge", func(t *testing.T) { resp, err := faucet.GetAllowedManaPledgeNodeIDs() diff --git a/tools/integration-tests/tester/tests/value/value_test.go b/tools/integration-tests/tester/tests/value/value_test.go index dbacfbbc9c..38e7fb66f5 100644 --- a/tools/integration-tests/tester/tests/value/value_test.go +++ b/tools/integration-tests/tester/tests/value/value_test.go @@ -4,19 +4,14 @@ import ( "context" "log" "testing" - "time" "github.com/iotaledger/hive.go/bitmask" "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/generics/lo" - "github.com/iotaledger/hive.go/identity" - "github.com/mr-tron/base58" "github.com/stretchr/testify/require" "github.com/iotaledger/goshimmer/client/wallet" - "github.com/iotaledger/goshimmer/client/wallet/packages/address" "github.com/iotaledger/goshimmer/client/wallet/packages/createnftoptions" - "github.com/iotaledger/goshimmer/client/wallet/packages/delegateoptions" "github.com/iotaledger/goshimmer/client/wallet/packages/destroynftoptions" walletseed "github.com/iotaledger/goshimmer/client/wallet/packages/seed" "github.com/iotaledger/goshimmer/packages/consensus/gof" @@ -203,110 +198,6 @@ func TestValueAliasPersistence(t *testing.T) { } } -// TestValueAliasDelegation tests if a delegation output can be used to refresh mana. -func TestValueAliasDelegation(t *testing.T) { - t.Skip("Value Alias Delegation test needs to be fixed.") - snapshotInfo := tests.EqualSnapshotDetails - ctx, cancel := tests.Context(context.Background(), t) - defer cancel() - n, err := f.CreateNetwork(ctx, t.Name(), 4, framework.CreateNetworkConfig{ - StartSynced: true, - Faucet: true, - Activity: true, // we need to issue regular activity messages - PeerMaster: true, - Snapshot: snapshotInfo, - }, tests.CommonSnapshotConfigFunc(t, snapshotInfo)) - require.NoError(t, err) - defer tests.ShutdownNetwork(ctx, t, n) - - faucet, nonFaucetPeers := n.Peers()[0], n.Peers()[1:] - - // check consensus mana: all nodes should have equal mana - require.Eventually(t, func() bool { - return tests.Mana(t, faucet).Consensus > 0 - }, tests.Timeout, tests.Tick) - require.EqualValues(t, snapshotInfo.GenesisTokenAmount, tests.Mana(t, faucet).Consensus) - - for i, peer := range nonFaucetPeers { - if snapshotInfo.PeersAmountsPledged[i] > 0 { - require.Eventually(t, func() bool { - return tests.Mana(t, peer).Consensus > 0 - }, tests.Timeout, tests.Tick) - } - require.EqualValues(t, snapshotInfo.PeersAmountsPledged[i], tests.Mana(t, peer).Consensus) - } - - tests.AwaitInitialFaucetOutputsPrepared(t, faucet, n.Peers()) - - // create a wallet that connects to a random peer - w := wallet.New(wallet.WebAPI(nonFaucetPeers[0].BaseURL()), wallet.FaucetPowDifficulty(faucet.Config().Faucet.PowDifficulty)) - - err = w.RequestFaucetFunds(true) - require.NoError(t, err) - - dumbWallet := createWallets(1)[0] - delegationAddress := dumbWallet.address - _, delegationIDs, err := w.DelegateFunds( - delegateoptions.Destination(address.Address{AddressBytes: delegationAddress.Array()}, map[devnetvm.Color]uint64{devnetvm.ColorIOTA: 1000}), - delegateoptions.WaitForConfirmation(true), - ) - require.NoError(t, err) - - delegatedAliasOutputID := utxo.OutputID{} - delegatedAliasOutput := &devnetvm.AliasOutput{} - for i, peer := range n.Peers() { - resp, err := peer.GetAddressUnspentOutputs(delegationIDs[0].Base58()) - require.NoError(t, err) - // there should be only this output - require.True(t, len(resp.Outputs) == 1) - shouldBeAliasOutput, err := resp.Outputs[0].ToLedgerstateOutput() - require.NoError(t, err) - require.Equal(t, devnetvm.AliasOutputType, shouldBeAliasOutput.Type()) - alias, ok := shouldBeAliasOutput.(*devnetvm.AliasOutput) - require.True(t, ok) - require.Equal(t, delegationIDs[0].Base58(), alias.GetAliasAddress().Base58()) - require.True(t, alias.IsDelegated()) - switch i { - case 0: - delegatedAliasOutputID = alias.ID() - delegatedAliasOutput = alias - default: - require.Equal(t, delegatedAliasOutputID.Base58(), alias.ID().Base58()) - require.Equal(t, lo.PanicOnErr(delegatedAliasOutput.Bytes()), lo.PanicOnErr(alias.Bytes())) - } - } - - aManaReceiver, err := identity.RandomID() - require.NoError(t, err) - cManaReceiver, err := identity.RandomID() - require.NoError(t, err) - - // let's try to "refresh mana" - nextOutput := delegatedAliasOutput.NewAliasOutputNext(false) - essence := devnetvm.NewTransactionEssence(0, time.Now(), - aManaReceiver, cManaReceiver, - devnetvm.NewInputs(devnetvm.NewUTXOInput(delegatedAliasOutputID)), - devnetvm.NewOutputs(nextOutput)) - tx := devnetvm.NewTransaction(essence, dumbWallet.unlockBlocks(essence)) - _, err = nonFaucetPeers[0].PostTransaction(lo.PanicOnErr(tx.Bytes())) - require.NoError(t, err) - - tests.RequireGradeOfFinalityEqual(t, n.Peers(), map[string]tests.ExpectedState{ - tx.ID().Base58(): { - GradeOfFinality: tests.GoFPointer(gof.High), - }, - }, tests.Timeout, tests.Tick) - - aManaReceiverCurrMana, err := nonFaucetPeers[0].GetManaFullNodeID(base58.Encode(aManaReceiver.Bytes())) - require.NoError(t, err) - cManaReceiverCurrMana, err := nonFaucetPeers[0].GetManaFullNodeID(base58.Encode(cManaReceiver.Bytes())) - require.NoError(t, err) - - // check that the pledge actually worked - require.True(t, aManaReceiverCurrMana.Access > 0) - require.True(t, cManaReceiverCurrMana.Consensus > 0) -} - func checkAliasOutputOnAllPeers(t *testing.T, peers []*framework.Node, aliasAddr *devnetvm.AliasAddress) utxo.OutputID { aliasOutputID := utxo.OutputID{}