Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:iotaledger/iota.go into feat/tar…
Browse files Browse the repository at this point in the history
…get-committee-size

# Conflicts:
#	api_protocol_parameters.go
#	api_test.go
#	nodeclient/apimodels/core_test.go
  • Loading branch information
alexsporn committed Nov 8, 2023
2 parents 407da3c + 60cfb40 commit 7d43645
Show file tree
Hide file tree
Showing 36 changed files with 555 additions and 401 deletions.
6 changes: 5 additions & 1 deletion api.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ type ProtocolParameters interface {
NetworkID() NetworkID
// Bech32HRP defines the HRP prefix used for Bech32 addresses in the network.
Bech32HRP() NetworkPrefix
// StorageScoreStructure defines the storage score structure used by the given network.
// StorageScoreParameters defines the storage score structure used by the given network.
StorageScoreParameters() *StorageScoreParameters
// WorkScoreParameters defines the work score parameters used by the given network.
WorkScoreParameters() *WorkScoreParameters
Expand All @@ -119,6 +119,10 @@ type ProtocolParameters interface {
// TokenSupply defines the current token supply on the network.
TokenSupply() BaseToken

// GenesisBlockID defines the block ID of the genesis block.
GenesisBlockID() BlockID
// GenesisSlot defines the slot of the genesis.
GenesisSlot() SlotIndex
// GenesisUnixTimestamp defines the genesis timestamp at which the slots start to count.
GenesisUnixTimestamp() int64
// SlotDurationInSeconds defines the duration of each slot in seconds.
Expand Down
21 changes: 12 additions & 9 deletions api/epoch_based_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/lo"
"github.com/iotaledger/hive.go/runtime/options"
"github.com/iotaledger/hive.go/serializer/v2/marshalutil"
"github.com/iotaledger/hive.go/serializer/v2/stream"
iotago "github.com/iotaledger/iota.go/v4"
)

Expand Down Expand Up @@ -167,10 +167,15 @@ func (e *EpochBasedProvider) VersionsAndProtocolParametersHash() (iotago.Identif
e.mutex.RLock()
defer e.mutex.RUnlock()

util := marshalutil.New()
byteBuffer := stream.NewByteBuffer()

for _, version := range e.protocolVersions.Slice() {
util.WriteBytes(lo.PanicOnErr(version.Version.Bytes()))
util.WriteUint64(uint64(version.StartEpoch))
if err := stream.Write(byteBuffer, version.Version); err != nil {
return iotago.Identifier{}, ierrors.Wrap(err, "failed to write Version")
}
if err := stream.Write(byteBuffer, version.StartEpoch); err != nil {
return iotago.Identifier{}, ierrors.Wrap(err, "failed to write StartEpoch")
}

var paramsHash iotago.Identifier
params, paramsExist := e.protocolParametersByVersion[version.Version]
Expand All @@ -186,14 +191,12 @@ func (e *EpochBasedProvider) VersionsAndProtocolParametersHash() (iotago.Identif
}
}

hashBytes, err := paramsHash.Bytes()
if err != nil {
return iotago.Identifier{}, ierrors.Wrap(err, "failed to get protocol parameters hash bytes")
if err := stream.Write(byteBuffer, paramsHash); err != nil {
return iotago.Identifier{}, ierrors.Wrap(err, "failed to write protocol parameters hash bytes")
}
util.WriteBytes(hashBytes)
}

return iotago.IdentifierFromData(util.Bytes()), nil
return iotago.IdentifierFromData(lo.PanicOnErr(byteBuffer.Bytes())), nil
}

func (e *EpochBasedProvider) ProtocolParameters(version iotago.Version) iotago.ProtocolParameters {
Expand Down
33 changes: 18 additions & 15 deletions api_protocol_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,48 @@ type basicProtocolParameters struct {
// TokenSupply defines the current token supply on the network.
TokenSupply BaseToken `serix:"6,mapKey=tokenSupply"`

// GenesisSlot defines the slot of the genesis.
GenesisSlot SlotIndex `serix:"7,mapKey=genesisSlot"`
// GenesisUnixTimestamp defines the genesis timestamp at which the slots start to count.
GenesisUnixTimestamp int64 `serix:"7,mapKey=genesisUnixTimestamp"`
GenesisUnixTimestamp int64 `serix:"8,mapKey=genesisUnixTimestamp"`
// SlotDurationInSeconds defines the duration of each slot in seconds.
SlotDurationInSeconds uint8 `serix:"8,mapKey=slotDurationInSeconds"`
SlotDurationInSeconds uint8 `serix:"9,mapKey=slotDurationInSeconds"`
// SlotsPerEpochExponent is the number of slots in an epoch expressed as an exponent of 2.
// (2**SlotsPerEpochExponent) == slots in an epoch.
SlotsPerEpochExponent uint8 `serix:"9,mapKey=slotsPerEpochExponent"`
SlotsPerEpochExponent uint8 `serix:"10,mapKey=slotsPerEpochExponent"`

// StakingUnbondingPeriod defines the unbonding period in epochs before an account can stop staking.
StakingUnbondingPeriod EpochIndex `serix:"10,mapKey=stakingUnbondingPeriod"`
StakingUnbondingPeriod EpochIndex `serix:"11,mapKey=stakingUnbondingPeriod"`
// ValidationBlocksPerSlot is the number of validation blocks that each validator should issue each slot.
ValidationBlocksPerSlot uint8 `serix:"11,mapKey=validationBlocksPerSlot"`
ValidationBlocksPerSlot uint8 `serix:"12,mapKey=validationBlocksPerSlot"`
// PunishmentEpochs is the number of epochs worth of Mana that a node is punished with for each additional validation block it issues.
PunishmentEpochs EpochIndex `serix:"12,mapKey=punishmentEpochs"`
PunishmentEpochs EpochIndex `serix:"13,mapKey=punishmentEpochs"`

// LivenessThresholdLowerBound is used by tip-selection to determine if a block is eligible by evaluating issuingTimes.
// and commitments in its past-cone to ATT and lastCommittedSlot respectively.
LivenessThresholdLowerBoundInSeconds uint16 `serix:"13,mapKey=livenessThresholdLowerBound"`
LivenessThresholdLowerBoundInSeconds uint16 `serix:"14,mapKey=livenessThresholdLowerBound"`
// LivenessThresholdUpperBound is used by tip-selection to determine if a block is eligible by evaluating issuingTimes
// and commitments in its past-cone to ATT and lastCommittedSlot respectively.
LivenessThresholdUpperBoundInSeconds uint16 `serix:"14,mapKey=livenessThresholdUpperBound"`
LivenessThresholdUpperBoundInSeconds uint16 `serix:"15,mapKey=livenessThresholdUpperBound"`

// MinCommittableAge is the minimum age relative to the accepted tangle time slot index that a slot can be committed.
// For example, if the last accepted slot is in slot 100, and minCommittableAge=10, then the latest committed slot can be at most 100-10=90.
MinCommittableAge SlotIndex `serix:"15,mapKey=minCommittableAge"`
MinCommittableAge SlotIndex `serix:"16,mapKey=minCommittableAge"`
// MaxCommittableAge is the maximum age for a slot commitment to be included in a block relative to the slot index of the block issuing time.
// For example, if the last accepted slot is in slot 100, and maxCommittableAge=20, then the oldest referencable commitment is 100-20=80.
MaxCommittableAge SlotIndex `serix:"16,mapKey=maxCommittableAge"`
MaxCommittableAge SlotIndex `serix:"17,mapKey=maxCommittableAge"`
// EpochNearingThreshold is used by the epoch orchestrator to detect the slot that should trigger a new committee
// selection for the next and upcoming epoch.
EpochNearingThreshold SlotIndex `serix:"17,mapKey=epochNearingThreshold"`
EpochNearingThreshold SlotIndex `serix:"18,mapKey=epochNearingThreshold"`
// RMCParameters defines the parameters used by to calculate the Reference Mana Cost (RMC).
CongestionControlParameters CongestionControlParameters `serix:"18,mapKey=congestionControlParameters"`
CongestionControlParameters CongestionControlParameters `serix:"19,mapKey=congestionControlParameters"`
// VersionSignaling defines the parameters used for version upgrades.
VersionSignaling VersionSignaling `serix:"19,mapKey=versionSignaling"`
VersionSignaling VersionSignaling `serix:"20,mapKey=versionSignaling"`
// RewardsParameters defines the parameters used for reward calculation.
RewardsParameters RewardsParameters `serix:"20,mapKey=rewardsParameters"`
RewardsParameters RewardsParameters `serix:"21,mapKey=rewardsParameters"`

// TargetCommitteeSize defines the target size of the committee. If there's fewer candidates the actual committee size could be smaller in a given epoch.
TargetCommitteeSize uint8 `serix:"21,mapKey=targetCommitteeSize"`
TargetCommitteeSize uint8 `serix:"22,mapKey=targetCommitteeSize"`
}

func (b basicProtocolParameters) Equals(other basicProtocolParameters) bool {
Expand All @@ -69,6 +71,7 @@ func (b basicProtocolParameters) Equals(other basicProtocolParameters) bool {
b.WorkScoreParameters.Equals(other.WorkScoreParameters) &&
b.ManaParameters.Equals(other.ManaParameters) &&
b.TokenSupply == other.TokenSupply &&
b.GenesisSlot == other.GenesisSlot &&
b.GenesisUnixTimestamp == other.GenesisUnixTimestamp &&
b.SlotDurationInSeconds == other.SlotDurationInSeconds &&
b.SlotsPerEpochExponent == other.SlotsPerEpochExponent &&
Expand Down
3 changes: 2 additions & 1 deletion api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func TestProtocolParametersJSONMarshalling(t *testing.T) {
10,
),
iotago.WithTimeProviderOptions(
654978,
1681373293,
10,
13,
Expand Down Expand Up @@ -135,7 +136,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,"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},"manaParameters":{"bitsCount":1,"generationRate":1,"generationRateExponent":27,"decayFactors":[10,20],"decayFactorsExponent":32,"decayFactorEpochsSum":1337,"decayFactorEpochsSumExponent":20},"tokenSupply":"1234567890987654321","genesisUnixTimestamp":"1681373293","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"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},"targetCommitteeSize":32}`
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},"manaParameters":{"bitsCount":1,"generationRate":1,"generationRateExponent":27,"decayFactors":[10,20],"decayFactorsExponent":32,"decayFactorEpochsSum":1337,"decayFactorEpochsSumExponent":20},"tokenSupply":"1234567890987654321","genesisSlot":654978,"genesisUnixTimestamp":"1681373293","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"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}"targetCommitteeSize":32}`

jsonProtoParams, err := tpkg.TestAPI.JSONEncode(protoParams)
require.NoError(t, err)
Expand Down
19 changes: 2 additions & 17 deletions api_v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func (v *v3api) Decode(b []byte, obj interface{}, opts ...serix.Option) (int, er
func V3API(protoParams ProtocolParameters) API {
api := CommonSerixAPI()

timeProvider := NewTimeProvider(protoParams.GenesisUnixTimestamp(), int64(protoParams.SlotDurationInSeconds()), protoParams.SlotsPerEpochExponent())
timeProvider := NewTimeProvider(protoParams.GenesisSlot(), protoParams.GenesisUnixTimestamp(), int64(protoParams.SlotDurationInSeconds()), protoParams.SlotsPerEpochExponent())

maxBlockWork, err := protoParams.WorkScoreParameters().MaxBlockWork()
must(err)
Expand Down Expand Up @@ -456,9 +456,6 @@ func V3API(protoParams ProtocolParameters) API {

{
must(api.RegisterTypeSettings(AccountOutput{}, serix.TypeSettings{}.WithObjectType(uint8(OutputAccount))))
must(api.RegisterValidators(AccountOutput{}, nil, func(ctx context.Context, account AccountOutput) error {
return account.syntacticallyValidate()
}))

must(api.RegisterTypeSettings(AccountOutputUnlockConditions{},
serix.TypeSettings{}.WithLengthPrefixType(serix.LengthPrefixTypeAsByte).WithArrayRules(accountOutputV3UnlockCondArrRules),
Expand All @@ -485,9 +482,6 @@ func V3API(protoParams ProtocolParameters) API {

{
must(api.RegisterTypeSettings(AnchorOutput{}, serix.TypeSettings{}.WithObjectType(uint8(OutputAnchor))))
must(api.RegisterValidators(AnchorOutput{}, nil, func(ctx context.Context, anchor AnchorOutput) error {
return anchor.syntacticallyValidate()
}))

must(api.RegisterTypeSettings(AnchorOutputUnlockConditions{},
serix.TypeSettings{}.WithLengthPrefixType(serix.LengthPrefixTypeAsByte).WithArrayRules(anchorOutputV3UnlockCondArrRules),
Expand Down Expand Up @@ -515,10 +509,6 @@ func V3API(protoParams ProtocolParameters) API {
must(api.RegisterTypeSettings(FoundryOutput{},
serix.TypeSettings{}.WithObjectType(uint8(OutputFoundry))),
)
must(api.RegisterValidators(FoundryOutput{}, nil, func(ctx context.Context, foundry FoundryOutput) error {
//nolint:contextcheck
return foundry.syntacticallyValidate()
}))

must(api.RegisterTypeSettings(FoundryOutputUnlockConditions{},
serix.TypeSettings{}.WithLengthPrefixType(serix.LengthPrefixTypeAsByte).WithArrayRules(foundryOutputV3UnlockCondArrRules),
Expand Down Expand Up @@ -547,9 +537,6 @@ func V3API(protoParams ProtocolParameters) API {
must(api.RegisterTypeSettings(NFTOutput{},
serix.TypeSettings{}.WithObjectType(uint8(OutputNFT))),
)
must(api.RegisterValidators(NFTOutput{}, nil, func(ctx context.Context, nft NFTOutput) error {
return nft.syntacticallyValidate()
}))

must(api.RegisterTypeSettings(NFTOutputUnlockConditions{},
serix.TypeSettings{}.WithLengthPrefixType(serix.LengthPrefixTypeAsByte).WithArrayRules(nftOutputV3UnlockCondArrRules),
Expand Down Expand Up @@ -578,9 +565,6 @@ func V3API(protoParams ProtocolParameters) API {

{
must(api.RegisterTypeSettings(DelegationOutput{}, serix.TypeSettings{}.WithObjectType(uint8(OutputDelegation))))
must(api.RegisterValidators(DelegationOutput{}, nil, func(ctx context.Context, delegation DelegationOutput) error {
return delegation.syntacticallyValidate()
}))

must(api.RegisterTypeSettings(DelegationOutputUnlockConditions{},
serix.TypeSettings{}.WithLengthPrefixType(serix.LengthPrefixTypeAsByte).WithArrayRules(delegationOutputV3UnlockCondArrRules),
Expand Down Expand Up @@ -701,6 +685,7 @@ func V3API(protoParams ProtocolParameters) API {

{
merklehasher.RegisterSerixRules[*APIByter[TxEssenceOutput]](api)
merklehasher.RegisterSerixRules[Identifier](api)
}

return v3
Expand Down
18 changes: 15 additions & 3 deletions api_v3_protocol_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func NewV3ProtocolParameters(opts ...options.Option[V3ProtocolParameters]) *V3Pr
WithNetworkOptions("testnet", PrefixTestnet),
WithSupplyOptions(1813620509061365, 100, 1, 10, 100, 100, 100),
WithWorkScoreOptions(0, 1, 0, 0, 0, 0, 0, 0, 0, 0),
WithTimeProviderOptions(time.Now().Unix(), 10, 13),
WithTimeProviderOptions(0, time.Now().Unix(), 10, 13),
WithManaOptions(63,
1,
17,
Expand Down Expand Up @@ -80,6 +80,16 @@ func (p *V3ProtocolParameters) NetworkID() NetworkID {
return NetworkIDFromString(p.basicProtocolParameters.NetworkName)
}

// GenesisBlockID defines the block ID of the genesis block.
func (p *V3ProtocolParameters) GenesisBlockID() BlockID {
return NewBlockID(p.basicProtocolParameters.GenesisSlot, EmptyIdentifier)
}

// GenesisSlot defines the genesis slot.
func (p *V3ProtocolParameters) GenesisSlot() SlotIndex {
return p.basicProtocolParameters.GenesisSlot
}

// GenesisUnixTimestamp defines the genesis timestamp at which the slots start to count.
func (p *V3ProtocolParameters) GenesisUnixTimestamp() int64 {
return p.basicProtocolParameters.GenesisUnixTimestamp
Expand Down Expand Up @@ -164,14 +174,15 @@ func (p *V3ProtocolParameters) Hash() (Identifier, error) {
}

func (p *V3ProtocolParameters) String() string {
return fmt.Sprintf("ProtocolParameters: {\n\tVersion: %d\n\tNetwork Name: %s\n\tBech32 HRP Prefix: %s\n\tStorageScore Structure: %v\n\tWorkScore Structure: %v\n\tMana Structure: %v\n\tToken Supply: %d\n\tGenesis Unix Timestamp: %d\n\tSlot Duration in Seconds: %d\n\tSlots per Epoch Exponent: %d\n\tStaking Unbonding Period: %d\n\tValidation Blocks per Slot: %d\n\tPunishment Epochs: %d\n\tLiveness Threshold Lower Bound: %d\n\tLiveness Threshold Upper Bound: %d\n\tMin Committable Age: %d\n\tMax Committable Age: %d\n\tEpoch Nearing Threshold: %d\n\tCongestion Control parameters: %v\n\tVersion Signaling: %v\n\tRewardsParameters: %v\n",
return fmt.Sprintf("ProtocolParameters: {\n\tVersion: %d\n\tNetwork Name: %s\n\tBech32 HRP Prefix: %s\n\tStorageScore Structure: %v\n\tWorkScore Structure: %v\n\tMana Structure: %v\n\tToken Supply: %d\n\tGenesis Slot: %d\n\tGenesis Unix Timestamp: %d\n\tSlot Duration in Seconds: %d\n\tSlots per Epoch Exponent: %d\n\tStaking Unbonding Period: %d\n\tValidation Blocks per Slot: %d\n\tPunishment Epochs: %d\n\tLiveness Threshold Lower Bound: %d\n\tLiveness Threshold Upper Bound: %d\n\tMin Committable Age: %d\n\tMax Committable Age: %d\n\tEpoch Nearing Threshold: %d\n\tCongestion Control parameters: %v\n\tVersion Signaling: %v\n\tRewardsParameters: %v\n",
p.basicProtocolParameters.Version,
p.basicProtocolParameters.NetworkName,
p.basicProtocolParameters.Bech32HRP,
p.basicProtocolParameters.StorageScoreParameters,
p.basicProtocolParameters.WorkScoreParameters,
p.basicProtocolParameters.ManaParameters,
p.basicProtocolParameters.TokenSupply,
p.basicProtocolParameters.GenesisSlot,
p.basicProtocolParameters.GenesisUnixTimestamp,
p.basicProtocolParameters.SlotDurationInSeconds,
p.basicProtocolParameters.SlotsPerEpochExponent,
Expand Down Expand Up @@ -265,8 +276,9 @@ func WithManaOptions(bitsCount uint8, generationRate uint8, generationRateExpone
}
}

func WithTimeProviderOptions(genesisTimestamp int64, slotDurationInSeconds uint8, slotsPerEpochExponent uint8) options.Option[V3ProtocolParameters] {
func WithTimeProviderOptions(genesisSlot SlotIndex, genesisTimestamp int64, slotDurationInSeconds uint8, slotsPerEpochExponent uint8) options.Option[V3ProtocolParameters] {
return func(p *V3ProtocolParameters) {
p.basicProtocolParameters.GenesisSlot = genesisSlot
p.basicProtocolParameters.GenesisUnixTimestamp = genesisTimestamp
p.basicProtocolParameters.SlotDurationInSeconds = slotDurationInSeconds
p.basicProtocolParameters.SlotsPerEpochExponent = slotsPerEpochExponent
Expand Down
8 changes: 5 additions & 3 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,10 @@ func (b *Block) syntacticallyValidate() error {
}
}

minCommittableAge := b.API.ProtocolParameters().MinCommittableAge()
maxCommittableAge := b.API.ProtocolParameters().MaxCommittableAge()
protocolParams := b.API.ProtocolParameters()
genesisSlot := protocolParams.GenesisSlot()
minCommittableAge := protocolParams.MinCommittableAge()
maxCommittableAge := protocolParams.MaxCommittableAge()
commitmentSlot := b.Header.SlotCommitmentID.Slot()
blockID, err := b.ID()
if err != nil {
Expand All @@ -299,7 +301,7 @@ func (b *Block) syntacticallyValidate() error {
blockSlot := blockID.Slot()

// check that commitment is not too recent.
if commitmentSlot > 0 && // Don't filter commitments to genesis based on being too recent.
if commitmentSlot > genesisSlot && // Don't filter commitments to genesis based on being too recent.
blockSlot < commitmentSlot+minCommittableAge {
return ierrors.Wrapf(ErrCommitmentTooRecent, "block at slot %d committing to slot %d", blockSlot, b.Header.SlotCommitmentID.Slot())
}
Expand Down
Loading

0 comments on commit 7d43645

Please sign in to comment.