diff --git a/api/epoch_based_provider.go b/api/epoch_based_provider.go index 02b4a343a..2c3ef5d66 100644 --- a/api/epoch_based_provider.go +++ b/api/epoch_based_provider.go @@ -2,6 +2,7 @@ package api import ( "sync" + "time" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/lo" @@ -19,16 +20,16 @@ type EpochBasedProvider struct { latestAPIMutex sync.RWMutex latestAPI iotago.API - currentAPIMutex sync.RWMutex - currentAPI iotago.API + committedAPIMutex sync.RWMutex + committedAPI iotago.API - currentSlotMutex sync.RWMutex - currentSlot iotago.SlotIndex + committedSlotMutex sync.RWMutex + committedSlot iotago.SlotIndex - optsAPIForMissingVersionCallback func(version iotago.Version) (iotago.API, error) + optsAPIForMissingVersionCallback func(protocolParameters iotago.ProtocolParameters) (iotago.API, error) } -func WithAPIForMissingVersionCallback(callback func(version iotago.Version) (iotago.API, error)) options.Option[EpochBasedProvider] { +func WithAPIForMissingVersionCallback(callback func(protocolParameters iotago.ProtocolParameters) (iotago.API, error)) options.Option[EpochBasedProvider] { return func(provider *EpochBasedProvider) { provider.optsAPIForMissingVersionCallback = callback } @@ -42,17 +43,17 @@ func NewEpochBasedProvider(opts ...options.Option[EpochBasedProvider]) *EpochBas }, opts) } -func (e *EpochBasedProvider) SetCurrentSlot(slot iotago.SlotIndex) { - e.currentSlotMutex.Lock() - e.currentSlot = slot - e.currentSlotMutex.Unlock() +func (e *EpochBasedProvider) SetCommittedSlot(slot iotago.SlotIndex) { + e.committedSlotMutex.Lock() + e.committedSlot = slot + e.committedSlotMutex.Unlock() - e.updateCurrentAPI(slot) + e.updateCommittedAPI(slot) } -func (e *EpochBasedProvider) updateCurrentAPI(slot iotago.SlotIndex) { - e.currentAPIMutex.Lock() - defer e.currentAPIMutex.Unlock() +func (e *EpochBasedProvider) updateCommittedAPI(slot iotago.SlotIndex) { + e.committedAPIMutex.Lock() + defer e.committedAPIMutex.Unlock() latestAPI := e.LatestAPI() if latestAPI == nil { @@ -62,8 +63,8 @@ func (e *EpochBasedProvider) updateCurrentAPI(slot iotago.SlotIndex) { epoch := latestAPI.TimeProvider().EpochFromSlot(slot) version := e.VersionForEpoch(epoch) - if e.currentAPI == nil || version > e.currentAPI.ProtocolParameters().Version() { - e.currentAPI = lo.PanicOnErr(e.apiForVersion(version)) + if e.committedAPI == nil || version > e.committedAPI.ProtocolParameters().Version() { + e.committedAPI = lo.PanicOnErr(e.apiForVersion(version)) } } @@ -91,10 +92,10 @@ func (e *EpochBasedProvider) AddVersion(version iotago.Version, epoch iotago.Epo e.protocolVersions.Add(version, epoch) e.mutex.Unlock() - e.currentSlotMutex.Lock() - defer e.currentSlotMutex.Unlock() + e.committedSlotMutex.Lock() + defer e.committedSlotMutex.Unlock() - e.updateCurrentAPI(e.currentSlot) + e.updateCommittedAPI(e.committedSlot) } func (e *EpochBasedProvider) AddFutureVersion(version iotago.Version, protocolParamsHash iotago.Identifier, epoch iotago.EpochIndex) { @@ -118,7 +119,7 @@ func (e *EpochBasedProvider) apiForVersion(version iotago.Version) (iotago.API, } if e.optsAPIForMissingVersionCallback != nil { - return e.optsAPIForMissingVersionCallback(version) + return e.optsAPIForMissingVersionCallback(protocolParams) } return nil, ierrors.Errorf("no api available for parameters with version %d", protocolParams.Version()) @@ -131,6 +132,16 @@ func (e *EpochBasedProvider) APIForVersion(version iotago.Version) (iotago.API, return e.apiForVersion(version) } +func (e *EpochBasedProvider) APIForTime(t time.Time) iotago.API { + e.mutex.RLock() + defer e.mutex.RUnlock() + + slot := e.latestAPI.TimeProvider().SlotFromTime(t) + epoch := e.latestAPI.TimeProvider().EpochFromSlot(slot) + + return lo.PanicOnErr(e.apiForVersion(e.protocolVersions.VersionForEpoch(epoch))) +} + func (e *EpochBasedProvider) APIForSlot(slot iotago.SlotIndex) iotago.API { e.mutex.RLock() defer e.mutex.RUnlock() @@ -154,11 +165,11 @@ func (e *EpochBasedProvider) LatestAPI() iotago.API { return e.latestAPI } -func (e *EpochBasedProvider) CurrentAPI() iotago.API { - e.currentAPIMutex.RLock() - defer e.currentAPIMutex.RUnlock() +func (e *EpochBasedProvider) CommittedAPI() iotago.API { + e.committedAPIMutex.RLock() + defer e.committedAPIMutex.RUnlock() - return e.currentAPI + return e.committedAPI } func (e *EpochBasedProvider) VersionsAndProtocolParametersHash() (iotago.Identifier, error) { @@ -238,7 +249,3 @@ func (e *EpochBasedProvider) VersionForSlot(slot iotago.SlotIndex) iotago.Versio return e.protocolVersions.VersionForEpoch(epoch) } - -func (e *EpochBasedProvider) IsFutureVersion(version iotago.Version) bool { - return e.CurrentAPI().Version() < version -} diff --git a/api/single_version_provider.go b/api/single_version_provider.go index 518926f93..6be1bee67 100644 --- a/api/single_version_provider.go +++ b/api/single_version_provider.go @@ -1,6 +1,8 @@ package api import ( + "time" + iotago "github.com/iotaledger/iota.go/v4" ) @@ -16,6 +18,10 @@ func (t *singleVersionProvider) APIForVersion(iotago.Version) (iotago.API, error return t.api, nil } +func (t *singleVersionProvider) APIForTime(time.Time) iotago.API { + return t.api +} + func (t *singleVersionProvider) APIForSlot(iotago.SlotIndex) iotago.API { return t.api } @@ -28,6 +34,6 @@ func (t *singleVersionProvider) LatestAPI() iotago.API { return t.api } -func (t *singleVersionProvider) CurrentAPI() iotago.API { +func (t *singleVersionProvider) CommittedAPI() iotago.API { return t.api } diff --git a/api_provider.go b/api_provider.go index 4a036efe2..6e8c01fef 100644 --- a/api_provider.go +++ b/api_provider.go @@ -1,17 +1,22 @@ package iotago +import "time" + type APIProvider interface { // APIForVersion returns the API for the given version. APIForVersion(Version) (API, error) + // APIForTime returns the API for the given time. + APIForTime(time.Time) API + // APIForSlot returns the API for the given slot. APIForSlot(SlotIndex) API // APIForEpoch returns the API for the given epoch. APIForEpoch(EpochIndex) API - // CurrentAPI returns the API for the current slot. - CurrentAPI() API + // CommittedAPI returns the API for the last committed slot. + CommittedAPI() API // LatestAPI returns the API for the latest supported protocol version. LatestAPI() API diff --git a/api_test.go b/api_test.go index b1b5fbc34..1ee6abf5b 100644 --- a/api_test.go +++ b/api_test.go @@ -135,7 +135,7 @@ func TestProtocolParametersJSONMarshalling(t *testing.T) { iotago.WithRewardsOptions(8, 8, 31, 1154, 2, 1), ) - protoParamsJSON := `{"type":0,"version":3,"networkName":"xxxNetwork","bech32Hrp":"xxx","storageScoreParameters":{"storageCost":"6","factorData":7,"offsetOutput":"8","offsetEd25519BlockIssuerKey":"9","offsetStakingFeature":"10","offsetDelegation":"10"},"workScoreParameters":{"dataByte":1,"block":2,"input":3,"contextInput":4,"output":5,"nativeToken":6,"staking":7,"blockIssuer":8,"allotment":9,"signatureEd25519":10},"tokenSupply":"1234567890987654321","genesisUnixTimestamp":"1681373293","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"manaParameters":{"bitsCount":1,"generationRate":1,"generationRateExponent":27,"decayFactors":[10,20],"decayFactorsExponent":32,"decayFactorEpochsSum":1337,"decayFactorEpochsSumExponent":20},"stakingUnbondingPeriod":11,"validationBlocksPerSlot":10,"punishmentEpochs":9,"livenessThresholdLowerBound":15,"livenessThresholdUpperBound":30,"minCommittableAge":10,"maxCommittableAge":20,"epochNearingThreshold":24,"congestionControlParameters":{"minReferenceManaCost":"500","increase":"500","decrease":"500","increaseThreshold":800000,"decreaseThreshold":500000,"schedulerRate":100000,"maxBufferSize":1000,"maxValidationBufferSize":100},"versionSignaling":{"windowSize":3,"windowTargetRatio":4,"activationOffset":1},"rewardsParameters":{"profitMarginExponent":8,"bootstrappingDuration":1154,"manaShareCoefficient":"2","decayBalancingConstantExponent":8,"decayBalancingConstant":"1","poolCoefficientExponent":31}}` + protoParamsJSON := `{"type":0,"version":3,"networkName":"xxxNetwork","bech32Hrp":"xxx","storageScoreParameters":{"storageCost":"6","factorData":7,"offsetOutputOverhead":"8","offsetEd25519BlockIssuerKey":"9","offsetStakingFeature":"10","offsetDelegation":"10"},"workScoreParameters":{"dataByte":1,"block":2,"input":3,"contextInput":4,"output":5,"nativeToken":6,"staking":7,"blockIssuer":8,"allotment":9,"signatureEd25519":10},"tokenSupply":"1234567890987654321","genesisUnixTimestamp":"1681373293","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"manaParameters":{"bitsCount":1,"generationRate":1,"generationRateExponent":27,"decayFactors":[10,20],"decayFactorsExponent":32,"decayFactorEpochsSum":1337,"decayFactorEpochsSumExponent":20},"stakingUnbondingPeriod":11,"validationBlocksPerSlot":10,"punishmentEpochs":9,"livenessThresholdLowerBound":15,"livenessThresholdUpperBound":30,"minCommittableAge":10,"maxCommittableAge":20,"epochNearingThreshold":24,"congestionControlParameters":{"minReferenceManaCost":"500","increase":"500","decrease":"500","increaseThreshold":800000,"decreaseThreshold":500000,"schedulerRate":100000,"maxBufferSize":1000,"maxValidationBufferSize":100},"versionSignaling":{"windowSize":3,"windowTargetRatio":4,"activationOffset":1},"rewardsParameters":{"profitMarginExponent":8,"bootstrappingDuration":1154,"manaShareCoefficient":"2","decayBalancingConstantExponent":8,"decayBalancingConstant":"1","poolCoefficientExponent":31}}` jsonProtoParams, err := tpkg.TestAPI.JSONEncode(protoParams) require.NoError(t, err) diff --git a/api_v3_protocol_parameters.go b/api_v3_protocol_parameters.go index 3e91d761a..c379c8ca6 100644 --- a/api_v3_protocol_parameters.go +++ b/api_v3_protocol_parameters.go @@ -192,13 +192,13 @@ func WithNetworkOptions(networkName string, bech32HRP NetworkPrefix) options.Opt } } -func WithSupplyOptions(totalSupply BaseToken, storageCost BaseToken, factorData StorageScoreFactor, offsetOutput, offsetEd25519BlockIssuerKey, offsetStakingFeature, offsetDelegation StorageScore) options.Option[V3ProtocolParameters] { +func WithSupplyOptions(totalSupply BaseToken, storageCost BaseToken, factorData StorageScoreFactor, offsetOutputOverhead, offsetEd25519BlockIssuerKey, offsetStakingFeature, offsetDelegation StorageScore) options.Option[V3ProtocolParameters] { return func(p *V3ProtocolParameters) { p.basicProtocolParameters.TokenSupply = totalSupply p.basicProtocolParameters.StorageScoreParameters = StorageScoreParameters{ StorageCost: storageCost, FactorData: factorData, - OffsetOutput: offsetOutput, + OffsetOutputOverhead: offsetOutputOverhead, OffsetEd25519BlockIssuerKey: offsetEd25519BlockIssuerKey, OffsetStakingFeature: offsetStakingFeature, OffsetDelegation: offsetDelegation, diff --git a/block_test.go b/block_test.go index 0adad0169..53b03fa6e 100644 --- a/block_test.go +++ b/block_test.go @@ -116,15 +116,15 @@ func createBlockAtSlotWithPayload(t *testing.T, blockIndex, commitmentIndex iota func TestProtocolBlock_ProtocolVersionSyntactical(t *testing.T) { apiProvider := api.NewEpochBasedProvider( api.WithAPIForMissingVersionCallback( - func(version iotago.Version) (iotago.API, error) { - return iotago.V3API(iotago.NewV3ProtocolParameters(iotago.WithVersion(version))), nil + func(parameters iotago.ProtocolParameters) (iotago.API, error) { + return iotago.V3API(iotago.NewV3ProtocolParameters(iotago.WithVersion(parameters.Version()))), nil }, ), ) apiProvider.AddProtocolParametersAtEpoch(iotago.NewV3ProtocolParameters(), 0) apiProvider.AddProtocolParametersAtEpoch(iotago.NewV3ProtocolParameters(iotago.WithVersion(4)), 3) - timeProvider := apiProvider.CurrentAPI().TimeProvider() + timeProvider := apiProvider.CommittedAPI().TimeProvider() require.ErrorIs(t, createBlockAtSlotWithVersion(t, timeProvider.EpochStart(1), 2, apiProvider), iotago.ErrInvalidBlockVersion) diff --git a/nodeclient/apimodels/core_test.go b/nodeclient/apimodels/core_test.go index d83e25578..b05893f99 100644 --- a/nodeclient/apimodels/core_test.go +++ b/nodeclient/apimodels/core_test.go @@ -61,7 +61,7 @@ func Test_InfoResponse(t *testing.T) { jsonResponse, err := api.JSONEncode(response) require.NoError(t, err) - expected := `{"name":"test","version":"2.0.0","status":{"isHealthy":false,"acceptedTangleTime":"1690879505000000000","relativeAcceptedTangleTime":"1690879505000000000","confirmedTangleTime":"1690879505000000000","relativeConfirmedTangleTime":"1690879505000000000","latestCommitmentId":"0x000000000000000000000000000000000000000000000000000000000000000000000000","latestFinalizedSlot":1,"latestAcceptedBlockSlot":2,"latestConfirmedBlockSlot":3,"pruningEpoch":4},"metrics":{"blocksPerSecond":"1.1E+00","confirmedBlocksPerSecond":"2.2E+00","confirmationRate":"3.3E+00"},"protocolParameters":[{"startEpoch":0,"parameters":{"type":0,"version":3,"networkName":"testnet","bech32Hrp":"rms","storageScoreParameters":{"storageCost":"100","factorData":1,"offsetOutput":"10","offsetEd25519BlockIssuerKey":"100","offsetStakingFeature":"100","offsetDelegation":"100"},"workScoreParameters":{"dataByte":0,"block":1,"input":0,"contextInput":0,"output":0,"nativeToken":0,"staking":0,"blockIssuer":0,"allotment":0,"signatureEd25519":0},"tokenSupply":"1813620509061365","genesisUnixTimestamp":"1690879505","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"manaParameters":{"bitsCount":63,"generationRate":1,"generationRateExponent":17,"decayFactors":[4291249941,4287535805,4283824883,4280117173,4276412671,4272711377,4269013285,4265318395,4261626702,4257938205,4254252900,4250570785,4246891856,4243216112,4239543550,4235874166,4232207957,4228544922,4224885058,4221228361,4217574829,4213924459,4210277249,4206633195,4202992295,4199354547,4195719947,4192088493,4188460182,4184835011,4181212978,4177594080,4173978314,4170365677,4166756168,4163149782,4159546518,4155946372,4152349343,4148755427,4145164621,4141576923,4137992331,4134410840,4130832450,4127257157,4123684959,4120115852,4116549834,4112986903,4109427055,4105870289,4102316601,4098765988,4095218449,4091673981,4088132580,4084594244,4081058971,4077526757,4073997601,4070471499,4066948449,4063428449,4059911495,4056397585,4052886716,4049378886,4045874092,4042372332,4038873602,4035377901,4031885225,4028395572,4024908939,4021425325,4017944725,4014467138,4010992560,4007520990,4004052425,4000586862,3997124298,3993664731,3990208159,3986754578,3983303986,3979856381,3976411760,3972970120,3969531459,3966095774,3962663063,3959233323,3955806551,3952382745,3948961903,3945544021,3942129098,3938717130,3935308116,3931902052,3928498936,3925098765,3921701537,3918307250,3914915900,3911527486,3908142004,3904759453,3901379829,3898003131,3894629355,3891258499,3887890560,3884525537,3881163426,3877804224,3874447931,3871094542,3867744056,3864396469,3861051780,3857709986,3854371084,3851035072,3847701948,3844371708,3841044351,3837719873,3834398273,3831079548,3827763695,3824450713,3821140597,3817833347,3814528959,3811227431,3807928760,3804632945,3801339982,3798049869,3794762604,3791478184,3788196607,3784917870,3781641970,3778368907,3775098676,3771831275,3768566702,3765304955,3762046031,3758789928,3755536643,3752286174,3749038518,3745793673,3742551636,3739312405,3736075978,3732842352,3729611525,3726383494,3723158258,3719935812,3716716156,3713499286,3710285201,3707073897,3703865373,3700659626,3697456653,3694256453,3691059023,3687864360,3684672462,3681483326,3678296951,3675113334,3671932472,3668754363,3665579005,3662406395,3659236531,3656069411,3652905032,3649743392,3646584488,3643428318,3640274880,3637124172,3633976190,3630830933,3627688398,3624548583,3621411486,3618277104,3615145434,3612016476,3608890225,3605766680,3602645839,3599527699,3596412257,3593299512,3590189461,3587082102,3583977433,3580875450,3577776153,3574679537,3571585602,3568494345,3565405764,3562319855,3559236618,3556156049,3553078146,3550002907,3546930330,3543860413,3540793152,3537728546,3534666593,3531607290,3528550634,3525496624,3522445258,3519396533,3516350446,3513306995,3510266179,3507227995,3504192440,3501159513,3498129210,3495101531,3492076472,3489054031,3486034206,3483016995,3480002395,3476990404,3473981020,3470974241,3467970065,3464968488,3461969510,3458973127,3455979337,3452988139,3449999530,3447013507,3444030069,3441049213,3438070937,3435095238,3432122115,3429151566,3426183587,3423218178,3420255335,3417295056,3414337339,3411382183,3408429584,3405479541,3402532051,3399587112,3396644722,3393704878,3390767579,3387832823,3384900606,3381970927,3379043784,3376119175,3373197097,3370277548,3367360525,3364446028,3361534053,3358624598,3355717662,3352813241,3349911335,3347011940,3344115054,3341220676,3338328803,3335439433,3332552563,3329668193,3326786318,3323906939,3321030051,3318155653,3315283743,3312414319,3309547378,3306682918,3303820938,3300961435,3298104407,3295249852,3292397767,3289548151,3286701001,3283856315,3281014092,3278174328,3275337023,3272502173,3269669777,3266839832,3264012336,3261187288,3258364685,3255544525,3252726806,3249911526,3247098682,3244288273,3241480296,3238674749,3235871631,3233070939,3230272671,3227476825,3224683399,3221892391,3219103798,3216317619,3213533851,3210752492,3207973541,3205196995,3202422853,3199651111,3196881768,3194114823,3191350272,3188588114,3185828346,3183070967,3180315975,3177563367,3174813142,3172065297,3169319830,3166576739,3163836023,3161097679,3158361705,3155628099,3152896859,3150167982,3147441468,3144717314,3141995517,3139276076,3136558989,3133844253,3131131867],"decayFactorsExponent":32,"decayFactorEpochsSum":2420916375,"decayFactorEpochsSumExponent":21},"stakingUnbondingPeriod":10,"validationBlocksPerSlot":10,"punishmentEpochs":10,"livenessThresholdLowerBound":15,"livenessThresholdUpperBound":30,"minCommittableAge":10,"maxCommittableAge":20,"epochNearingThreshold":24,"congestionControlParameters":{"minReferenceManaCost":"1","increase":"0","decrease":"0","increaseThreshold":800000,"decreaseThreshold":500000,"schedulerRate":100000,"maxBufferSize":1000,"maxValidationBufferSize":100},"versionSignaling":{"windowSize":7,"windowTargetRatio":5,"activationOffset":7},"rewardsParameters":{"profitMarginExponent":8,"bootstrappingDuration":1154,"manaShareCoefficient":"2","decayBalancingConstantExponent":8,"decayBalancingConstant":"1","poolCoefficientExponent":31}}}],"baseToken":{"name":"Shimmer","tickerSymbol":"SMR","unit":"SMR","subunit":"glow","decimals":6,"useMetricPrefix":false},"features":["test"]}` + expected := `{"name":"test","version":"2.0.0","status":{"isHealthy":false,"acceptedTangleTime":"1690879505000000000","relativeAcceptedTangleTime":"1690879505000000000","confirmedTangleTime":"1690879505000000000","relativeConfirmedTangleTime":"1690879505000000000","latestCommitmentId":"0x000000000000000000000000000000000000000000000000000000000000000000000000","latestFinalizedSlot":1,"latestAcceptedBlockSlot":2,"latestConfirmedBlockSlot":3,"pruningEpoch":4},"metrics":{"blocksPerSecond":"1.1E+00","confirmedBlocksPerSecond":"2.2E+00","confirmationRate":"3.3E+00"},"protocolParameters":[{"startEpoch":0,"parameters":{"type":0,"version":3,"networkName":"testnet","bech32Hrp":"rms","storageScoreParameters":{"storageCost":"100","factorData":1,"offsetOutputOverhead":"10","offsetEd25519BlockIssuerKey":"100","offsetStakingFeature":"100","offsetDelegation":"100"},"workScoreParameters":{"dataByte":0,"block":1,"input":0,"contextInput":0,"output":0,"nativeToken":0,"staking":0,"blockIssuer":0,"allotment":0,"signatureEd25519":0},"tokenSupply":"1813620509061365","genesisUnixTimestamp":"1690879505","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"manaParameters":{"bitsCount":63,"generationRate":1,"generationRateExponent":17,"decayFactors":[4291249941,4287535805,4283824883,4280117173,4276412671,4272711377,4269013285,4265318395,4261626702,4257938205,4254252900,4250570785,4246891856,4243216112,4239543550,4235874166,4232207957,4228544922,4224885058,4221228361,4217574829,4213924459,4210277249,4206633195,4202992295,4199354547,4195719947,4192088493,4188460182,4184835011,4181212978,4177594080,4173978314,4170365677,4166756168,4163149782,4159546518,4155946372,4152349343,4148755427,4145164621,4141576923,4137992331,4134410840,4130832450,4127257157,4123684959,4120115852,4116549834,4112986903,4109427055,4105870289,4102316601,4098765988,4095218449,4091673981,4088132580,4084594244,4081058971,4077526757,4073997601,4070471499,4066948449,4063428449,4059911495,4056397585,4052886716,4049378886,4045874092,4042372332,4038873602,4035377901,4031885225,4028395572,4024908939,4021425325,4017944725,4014467138,4010992560,4007520990,4004052425,4000586862,3997124298,3993664731,3990208159,3986754578,3983303986,3979856381,3976411760,3972970120,3969531459,3966095774,3962663063,3959233323,3955806551,3952382745,3948961903,3945544021,3942129098,3938717130,3935308116,3931902052,3928498936,3925098765,3921701537,3918307250,3914915900,3911527486,3908142004,3904759453,3901379829,3898003131,3894629355,3891258499,3887890560,3884525537,3881163426,3877804224,3874447931,3871094542,3867744056,3864396469,3861051780,3857709986,3854371084,3851035072,3847701948,3844371708,3841044351,3837719873,3834398273,3831079548,3827763695,3824450713,3821140597,3817833347,3814528959,3811227431,3807928760,3804632945,3801339982,3798049869,3794762604,3791478184,3788196607,3784917870,3781641970,3778368907,3775098676,3771831275,3768566702,3765304955,3762046031,3758789928,3755536643,3752286174,3749038518,3745793673,3742551636,3739312405,3736075978,3732842352,3729611525,3726383494,3723158258,3719935812,3716716156,3713499286,3710285201,3707073897,3703865373,3700659626,3697456653,3694256453,3691059023,3687864360,3684672462,3681483326,3678296951,3675113334,3671932472,3668754363,3665579005,3662406395,3659236531,3656069411,3652905032,3649743392,3646584488,3643428318,3640274880,3637124172,3633976190,3630830933,3627688398,3624548583,3621411486,3618277104,3615145434,3612016476,3608890225,3605766680,3602645839,3599527699,3596412257,3593299512,3590189461,3587082102,3583977433,3580875450,3577776153,3574679537,3571585602,3568494345,3565405764,3562319855,3559236618,3556156049,3553078146,3550002907,3546930330,3543860413,3540793152,3537728546,3534666593,3531607290,3528550634,3525496624,3522445258,3519396533,3516350446,3513306995,3510266179,3507227995,3504192440,3501159513,3498129210,3495101531,3492076472,3489054031,3486034206,3483016995,3480002395,3476990404,3473981020,3470974241,3467970065,3464968488,3461969510,3458973127,3455979337,3452988139,3449999530,3447013507,3444030069,3441049213,3438070937,3435095238,3432122115,3429151566,3426183587,3423218178,3420255335,3417295056,3414337339,3411382183,3408429584,3405479541,3402532051,3399587112,3396644722,3393704878,3390767579,3387832823,3384900606,3381970927,3379043784,3376119175,3373197097,3370277548,3367360525,3364446028,3361534053,3358624598,3355717662,3352813241,3349911335,3347011940,3344115054,3341220676,3338328803,3335439433,3332552563,3329668193,3326786318,3323906939,3321030051,3318155653,3315283743,3312414319,3309547378,3306682918,3303820938,3300961435,3298104407,3295249852,3292397767,3289548151,3286701001,3283856315,3281014092,3278174328,3275337023,3272502173,3269669777,3266839832,3264012336,3261187288,3258364685,3255544525,3252726806,3249911526,3247098682,3244288273,3241480296,3238674749,3235871631,3233070939,3230272671,3227476825,3224683399,3221892391,3219103798,3216317619,3213533851,3210752492,3207973541,3205196995,3202422853,3199651111,3196881768,3194114823,3191350272,3188588114,3185828346,3183070967,3180315975,3177563367,3174813142,3172065297,3169319830,3166576739,3163836023,3161097679,3158361705,3155628099,3152896859,3150167982,3147441468,3144717314,3141995517,3139276076,3136558989,3133844253,3131131867],"decayFactorsExponent":32,"decayFactorEpochsSum":2420916375,"decayFactorEpochsSumExponent":21},"stakingUnbondingPeriod":10,"validationBlocksPerSlot":10,"punishmentEpochs":10,"livenessThresholdLowerBound":15,"livenessThresholdUpperBound":30,"minCommittableAge":10,"maxCommittableAge":20,"epochNearingThreshold":24,"congestionControlParameters":{"minReferenceManaCost":"1","increase":"0","decrease":"0","increaseThreshold":800000,"decreaseThreshold":500000,"schedulerRate":100000,"maxBufferSize":1000,"maxValidationBufferSize":100},"versionSignaling":{"windowSize":7,"windowTargetRatio":5,"activationOffset":7},"rewardsParameters":{"profitMarginExponent":8,"bootstrappingDuration":1154,"manaShareCoefficient":"2","decayBalancingConstantExponent":8,"decayBalancingConstant":"1","poolCoefficientExponent":31}}}],"baseToken":{"name":"Shimmer","tickerSymbol":"SMR","unit":"SMR","subunit":"glow","decimals":6,"useMetricPrefix":false},"features":["test"]}` require.Equal(t, expected, string(jsonResponse)) decoded := new(apimodels.InfoResponse) diff --git a/nodeclient/blockissuer_client.go b/nodeclient/blockissuer_client.go index e3b352cb7..5d7962139 100644 --- a/nodeclient/blockissuer_client.go +++ b/nodeclient/blockissuer_client.go @@ -72,7 +72,7 @@ func (client *blockIssuerClient) Info(ctx context.Context) (*BlockIssuerInfo, er } func (client *blockIssuerClient) mineNonceAndSendPayload(ctx context.Context, payload iotago.BlockPayload, commitmentID iotago.CommitmentID, powTargetTrailingZeros uint8, numPoWWorkers ...int) (*apimodels.BlockCreatedResponse, error) { - payloadBytes, err := client.core.CurrentAPI().Encode(payload, serix.WithValidation()) + payloadBytes, err := client.core.CommittedAPI().Encode(payload, serix.WithValidation()) if err != nil { return nil, ierrors.Wrap(err, "failed to encode the payload") } diff --git a/nodeclient/event_api_client.go b/nodeclient/event_api_client.go index 18e9eb963..72270e8b1 100644 --- a/nodeclient/event_api_client.go +++ b/nodeclient/event_api_client.go @@ -221,7 +221,7 @@ func subscribeToTopic[T any](eac *EventAPIClient, topic string, deseriFunc func( func (eac *EventAPIClient) subscribeToOutputsTopic(topic string) (<-chan iotago.Output, *EventAPIClientSubscription) { return subscribeToTopic(eac, topic, func(payload []byte) (iotago.Output, error) { var output iotago.TxEssenceOutput - if err := eac.Client.CurrentAPI().JSONDecode(payload, &output); err != nil { + if err := eac.Client.CommittedAPI().JSONDecode(payload, &output); err != nil { sendErrOrDrop(eac.Errors, err) return nil, err } @@ -233,7 +233,7 @@ func (eac *EventAPIClient) subscribeToOutputsTopic(topic string) (<-chan iotago. func (eac *EventAPIClient) subscribeToBlockMetadataTopic(topic string) (<-chan *apimodels.BlockMetadataResponse, *EventAPIClientSubscription) { return subscribeToTopic(eac, topic, func(payload []byte) (*apimodels.BlockMetadataResponse, error) { response := new(apimodels.BlockMetadataResponse) - if err := eac.Client.CurrentAPI().JSONDecode(payload, response); err != nil { + if err := eac.Client.CommittedAPI().JSONDecode(payload, response); err != nil { sendErrOrDrop(eac.Errors, err) return nil, err } @@ -373,7 +373,7 @@ func (eac *EventAPIClient) OutputMetadata(outputID iotago.OutputID) (<-chan *api return subscribeToTopic(eac, topic, func(payload []byte) (*apimodels.OutputMetadata, error) { response := new(apimodels.OutputMetadata) - if err := eac.Client.CurrentAPI().JSONDecode(payload, response); err != nil { + if err := eac.Client.CommittedAPI().JSONDecode(payload, response); err != nil { sendErrOrDrop(eac.Errors, err) return nil, err } diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index 0a13558d0..399814d30 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -282,13 +282,13 @@ func (client *Client) HTTPClient() *http.Client { // Do executes a request against the endpoint. // This function is only meant to be used for special routes not covered through the standard API. func (client *Client) Do(ctx context.Context, method string, route string, reqObj interface{}, resObj interface{}) (*http.Response, error) { - return do(ctx, client.CurrentAPI().Underlying(), client.opts.httpClient, client.BaseURL, client.opts.userInfo, method, route, client.opts.requestURLHook, nil, reqObj, resObj) + return do(ctx, client.CommittedAPI().Underlying(), client.opts.httpClient, client.BaseURL, client.opts.userInfo, method, route, client.opts.requestURLHook, nil, reqObj, resObj) } // DoWithRequestHeaderHook executes a request against the endpoint. // This function is only meant to be used for special routes not covered through the standard API. func (client *Client) DoWithRequestHeaderHook(ctx context.Context, method string, route string, requestHeaderHook RequestHeaderHook, reqObj interface{}, resObj interface{}) (*http.Response, error) { - return do(ctx, client.CurrentAPI().Underlying(), client.opts.httpClient, client.BaseURL, client.opts.userInfo, method, route, client.opts.requestURLHook, requestHeaderHook, reqObj, resObj) + return do(ctx, client.CommittedAPI().Underlying(), client.opts.httpClient, client.BaseURL, client.opts.userInfo, method, route, client.opts.requestURLHook, requestHeaderHook, reqObj, resObj) } // Indexer returns the IndexerClient. @@ -367,7 +367,7 @@ func (client *Client) Info(ctx context.Context) (*apimodels.InfoResponse, error) return nil, err } - client.apiProvider.SetCurrentSlot(res.Status.LatestCommitmentID.Slot()) + client.apiProvider.SetCommittedSlot(res.Status.LatestCommitmentID.Slot()) return res, nil } @@ -569,7 +569,7 @@ func (client *Client) OutputByID(ctx context.Context, outputID iotago.OutputID) } var outputResponse apimodels.OutputResponse - if _, err := client.CurrentAPI().Decode(res.Data, &outputResponse, serix.WithValidation()); err != nil { + if _, err := client.CommittedAPI().Decode(res.Data, &outputResponse, serix.WithValidation()); err != nil { return nil, err } @@ -596,7 +596,7 @@ func (client *Client) OutputWithMetadataByID(ctx context.Context, outputID iotag } var outputResponse apimodels.OutputWithMetadataResponse - if _, err := client.CurrentAPI().Decode(res.Data, &outputResponse, serix.WithValidation()); err != nil { + if _, err := client.CommittedAPI().Decode(res.Data, &outputResponse, serix.WithValidation()); err != nil { return nil, nil, err } @@ -740,12 +740,16 @@ func (client *Client) APIForEpoch(epoch iotago.EpochIndex) iotago.API { return client.apiProvider.APIForEpoch(epoch) } +func (client *Client) APIForTime(t time.Time) iotago.API { + return client.apiProvider.APIForTime(t) +} + func (client *Client) APIForSlot(slot iotago.SlotIndex) iotago.API { return client.apiProvider.APIForSlot(slot) } -func (client *Client) CurrentAPI() iotago.API { - return client.apiProvider.CurrentAPI() +func (client *Client) CommittedAPI() iotago.API { + return client.apiProvider.CommittedAPI() } func (client *Client) LatestAPI() iotago.API { diff --git a/output.go b/output.go index ada585031..a2dd9be1c 100644 --- a/output.go +++ b/output.go @@ -94,13 +94,6 @@ var ( ErrTransDepIdentOutputNextInvalid = ierrors.New("transition dependable ident output's next output is invalid") ) -// defines the default storage score offset for an output. -func offsetOutput(storageScoreStruct *StorageScoreStructure) StorageScore { - return storageScoreStruct.OffsetOutput() + - // included output id, block id, and slot booked data size - storageScoreStruct.FactorData().Multiply(OutputIDLength+BlockIDLength+SlotIndexLength) -} - // OutputSet is a map of the OutputID to Output. type OutputSet map[OutputID]Output diff --git a/output_account.go b/output_account.go index 4bb9a67c8..b641c8706 100644 --- a/output_account.go +++ b/output_account.go @@ -196,7 +196,7 @@ func (a *AccountOutput) UnlockableBy(ident Address, next TransDepIdentOutput, pa } func (a *AccountOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore { - return offsetOutput(storageScoreStruct) + + return storageScoreStruct.OffsetOutput + storageScoreStruct.FactorData().Multiply(StorageScore(a.Size())) + a.Conditions.StorageScore(storageScoreStruct, nil) + a.Features.StorageScore(storageScoreStruct, nil) + diff --git a/output_basic.go b/output_basic.go index 5da4e243b..9e77b7217 100644 --- a/output_basic.go +++ b/output_basic.go @@ -71,7 +71,7 @@ func (e *BasicOutput) UnlockableBy(ident Address, pastBoundedSlotIndex SlotIndex } func (e *BasicOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore { - return offsetOutput(storageScoreStruct) + + return storageScoreStruct.OffsetOutput + storageScoreStruct.FactorData().Multiply(StorageScore(e.Size())) + e.Conditions.StorageScore(storageScoreStruct, nil) + e.Features.StorageScore(storageScoreStruct, nil) diff --git a/output_delegation.go b/output_delegation.go index 98df2b5a3..97e58ac19 100644 --- a/output_delegation.go +++ b/output_delegation.go @@ -174,7 +174,7 @@ func (d *DelegationOutput) UnlockableBy(ident Address, pastBoundedSlot SlotIndex } func (d *DelegationOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore { - return offsetOutput(storageScoreStruct) + + return storageScoreStruct.OffsetOutput + storageScoreStruct.FactorData().Multiply(StorageScore(d.Size())) + storageScoreStruct.OffsetDelegation() + d.Conditions.StorageScore(storageScoreStruct, nil) diff --git a/output_foundry.go b/output_foundry.go index 28692ece5..12a55cf78 100644 --- a/output_foundry.go +++ b/output_foundry.go @@ -179,7 +179,7 @@ func (f *FoundryOutput) UnlockableBy(ident Address, pastBoundedSlotIndex SlotInd } func (f *FoundryOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore { - return offsetOutput(storageScoreStruct) + + return storageScoreStruct.OffsetOutput + storageScoreStruct.FactorData().Multiply(StorageScore(f.Size())) + f.TokenScheme.StorageScore(storageScoreStruct, nil) + f.Conditions.StorageScore(storageScoreStruct, nil) + diff --git a/output_nft.go b/output_nft.go index ce395a9c9..dc32600cb 100644 --- a/output_nft.go +++ b/output_nft.go @@ -162,7 +162,7 @@ func (n *NFTOutput) UnlockableBy(ident Address, pastBoundedSlotIndex SlotIndex, } func (n *NFTOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore { - return offsetOutput(storageScoreStruct) + + return storageScoreStruct.OffsetOutput + storageScoreStruct.FactorData().Multiply(StorageScore(n.Size())) + n.Conditions.StorageScore(storageScoreStruct, nil) + n.Features.StorageScore(storageScoreStruct, nil) + diff --git a/storagescore.go b/storagescore.go index 927ffc5c6..cdf9338a8 100644 --- a/storagescore.go +++ b/storagescore.go @@ -38,8 +38,8 @@ type StorageScoreParameters struct { StorageCost BaseToken `serix:"0,mapKey=storageCost"` // Defines the factor to be used for data only fields. FactorData StorageScoreFactor `serix:"1,mapKey=factorData"` - // Defines the offset to be used for key/lookup generating fields. - OffsetOutput StorageScore `serix:"2,mapKey=offsetOutput"` + // Defines the offset to be applied to all outputs for the overhead of handling them in storage. + OffsetOutputOverhead StorageScore `serix:"2,mapKey=offsetOutputOverhead"` // Defines the offset to be used for block issuer feature public keys. OffsetEd25519BlockIssuerKey StorageScore `serix:"3,mapKey=offsetEd25519BlockIssuerKey"` // Defines the offset to be used for staking feature. @@ -56,6 +56,7 @@ type StorageScoreStructure struct { // Basic Output (the Implicit Account Creation Address is contained in) results in the // minimum storage score of a block issuer account. OffsetImplicitAccountCreationAddress StorageScore + OffsetOutput StorageScore } // StorageCost returns the cost of a single unit of storage score denoted in base tokens. @@ -68,11 +69,6 @@ func (r *StorageScoreStructure) FactorData() StorageScoreFactor { return r.StorageScoreParameters.FactorData } -// OffsetOutput returns the offset to be used for all outputs to account for metadata created for the output. -func (r *StorageScoreStructure) OffsetOutput() StorageScore { - return r.StorageScoreParameters.OffsetOutput -} - // OffsetEd25519BlockIssuerKey returns the offset to be used for block issuer feature public keys. func (r *StorageScoreStructure) OffsetEd25519BlockIssuerKey() StorageScore { return r.StorageScoreParameters.OffsetEd25519BlockIssuerKey @@ -139,6 +135,10 @@ func NewStorageScoreStructure(storageScoreParameters *StorageScoreParameters) *S safemath.SafeSub(storageScoreAccountOutput, storageScoreBasicOutputWithoutAddress), ) + // Compute the OffsetOutput + metadataOffset := storageScoreStructure.FactorData().Multiply(OutputIDLength + BlockIDLength + SlotIndexLength) + storageScoreStructure.OffsetOutput = storageScoreParameters.OffsetOutputOverhead + metadataOffset + return storageScoreStructure } @@ -172,7 +172,7 @@ func (r *StorageScoreStructure) MinStorageDepositForReturnOutput(sender Address) func (r StorageScoreParameters) Equals(other StorageScoreParameters) bool { return r.StorageCost == other.StorageCost && r.FactorData == other.FactorData && - r.OffsetOutput == other.OffsetOutput && + r.OffsetOutputOverhead == other.OffsetOutputOverhead && r.OffsetEd25519BlockIssuerKey == other.OffsetEd25519BlockIssuerKey && r.OffsetStakingFeature == other.OffsetStakingFeature && r.OffsetDelegation == other.OffsetDelegation diff --git a/storagescore_test.go b/storagescore_test.go index 6b3b633bc..0934813b8 100644 --- a/storagescore_test.go +++ b/storagescore_test.go @@ -27,12 +27,12 @@ func TestStorageScoreParamtersJSONMarshalling(t *testing.T) { storageScoreParameters := &iotago.StorageScoreParameters{ StorageCost: 500, FactorData: 1, - OffsetOutput: 10, + OffsetOutputOverhead: 10, OffsetEd25519BlockIssuerKey: 50, OffsetStakingFeature: 100, OffsetDelegation: 100, } - storageScoreParametersJSON := `{"storageCost":"500","factorData":1,"offsetOutput":"10","offsetEd25519BlockIssuerKey":"50","offsetStakingFeature":"100","offsetDelegation":"100"}` + storageScoreParametersJSON := `{"storageCost":"500","factorData":1,"offsetOutputOverhead":"10","offsetEd25519BlockIssuerKey":"50","offsetStakingFeature":"100","offsetDelegation":"100"}` j, err := tpkg.TestAPI.JSONEncode(storageScoreParameters) require.NoError(t, err) diff --git a/tpkg/util.go b/tpkg/util.go index 3db8aa360..bec63c37b 100644 --- a/tpkg/util.go +++ b/tpkg/util.go @@ -977,7 +977,7 @@ func RandStorageScoreParameters() *iotago.StorageScoreParameters { return &iotago.StorageScoreParameters{ StorageCost: RandBaseToken(iotago.MaxBaseToken), FactorData: iotago.StorageScoreFactor(RandUint8(math.MaxUint8)), - OffsetOutput: iotago.StorageScore(RandUint64(math.MaxUint64)), + OffsetOutputOverhead: iotago.StorageScore(RandUint64(math.MaxUint64)), OffsetEd25519BlockIssuerKey: iotago.StorageScore(RandUint64(math.MaxUint64)), OffsetStakingFeature: iotago.StorageScore(RandUint64(math.MaxUint64)), }