Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scheduler params and max block work and activate workscore #479

Merged
merged 24 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
273784a
define MaxBlockWorkScore
cyberphysic4l Aug 10, 2023
eaaabd0
Merge branch 'serix-iota-core' into feat/scheduler-params
cyberphysic4l Aug 10, 2023
0b17804
Add MaxBlockWork to API
cyberphysic4l Aug 11, 2023
4d6eac7
combine RMC params and scheduler params into CongestionControlParameters
cyberphysic4l Aug 11, 2023
05d0b70
deal with nil payloads in blocks for workscore calculation
cyberphysic4l Aug 11, 2023
d9c787a
correct spelling on minimum in MinMana description
cyberphysic4l Aug 11, 2023
3e32594
deal with nil payload in tx essence
cyberphysic4l Aug 14, 2023
8b75b9e
calculate burned Mana using workscore in block builder
cyberphysic4l Aug 14, 2023
94380d1
Move DataByte factor to only be calculated in the block workscore rat…
cyberphysic4l Aug 14, 2023
17a27bf
Fix issue with size calculation in block
jonastheis Aug 15, 2023
e90061f
burn correct mana in random blocks
cyberphysic4l Aug 15, 2023
9e1e0c0
set workScore defaults in testAPI to give workscore = 1 for all blocks
cyberphysic4l Aug 15, 2023
18f5c2c
Merge branch 'serix-iota-core' into feat/scheduler-params
cyberphysic4l Aug 15, 2023
05301e5
correct kilobyte factor in workscore
cyberphysic4l Aug 16, 2023
d17dad9
Merge branch 'serix-iota-core' into feat/scheduler-params
cyberphysic4l Aug 16, 2023
3da2006
default protocol params to give RMC=1 and workscore=1 for all blocks
cyberphysic4l Aug 16, 2023
24b3855
always burn 1 Mana by default
cyberphysic4l Aug 16, 2023
aa51e92
fix info response test
cyberphysic4l Aug 16, 2023
9c899be
Merge remote-tracking branch 'origin/fix/node-client-serialier-versio…
cyberphysic4l Aug 16, 2023
6868590
Merge branch 'serix-iota-core' into feat/scheduler-params
cyberphysic4l Aug 16, 2023
17ab0d6
fix info response test
cyberphysic4l Aug 16, 2023
30fb31f
burn zero mana by default
cyberphysic4l Aug 16, 2023
f43f5e8
revert
cyberphysic4l Aug 16, 2023
6261ab6
Merge branch 'feat/scheduler-params' of https://github.com/iotaledger…
cyberphysic4l Aug 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions allotment.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,13 @@ func (a Allotments) Size() int {
}

func (a Allotments) WorkScore(workScoreStructure *WorkScoreStructure) (WorkScore, error) {
workScoreBytes, err := workScoreStructure.DataByte.Multiply(a.Size())
if err != nil {
return 0, err
}

// Allotments requires invocation of account managers, so requires extra work.
workScoreAllotments, err := workScoreStructure.Allotment.Multiply(len(a))
if err != nil {
return 0, err
}

return workScoreBytes.Add(workScoreAllotments)
return workScoreAllotments, nil
}

func (a Allotments) Get(id AccountID) Mana {
Expand Down
4 changes: 3 additions & 1 deletion api.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ type API interface {
ManaDecayProvider() *ManaDecayProvider
// LivenessThresholdDuration returns the liveness threshold duration.
LivenessThresholdDuration() time.Duration
// MaxBlockWork returns the maximum block work score.
MaxBlockWork() WorkScore
}

func LatestProtocolVersion() Version {
Expand Down Expand Up @@ -122,7 +124,7 @@ type ProtocolParameters interface {
EpochNearingThreshold() SlotIndex

// RMCParameters returns the parameters used to calculate reference Mana cost.
RMCParameters() *RMCParameters
CongestionControlParameters() *CongestionControlParameters

VersionSignaling() *VersionSignaling

Expand Down
4 changes: 2 additions & 2 deletions api_protocol_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type basicProtocolParameters struct {
// selection for the next and upcoming epoch.
EpochNearingThreshold SlotIndex `serix:"19,mapKey=epochNearingThreshold"`
// RMCParameters defines the parameters used by to calculate the Reference Mana Cost (RMC).
RMCParameters RMCParameters `serix:"20,mapKey=rmcParameters"`
CongestionControlParameters CongestionControlParameters `serix:"20,mapKey=congestionControlParameters"`

VersionSignaling VersionSignaling `serix:"21,mapKey=versionSignaling"`
}
Expand All @@ -83,6 +83,6 @@ func (b basicProtocolParameters) Equals(other basicProtocolParameters) bool {
b.MinCommittableAge == other.MinCommittableAge &&
b.MaxCommittableAge == other.MaxCommittableAge &&
b.EpochNearingThreshold == other.EpochNearingThreshold &&
b.RMCParameters.Equals(other.RMCParameters) &&
b.CongestionControlParameters.Equals(other.CongestionControlParameters) &&
b.VersionSignaling.Equals(other.VersionSignaling)
}
13 changes: 8 additions & 5 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func TestProtocolParameters_DeSerialize(t *testing.T) {
}

func TestProtocolParametersJSONMarshalling(t *testing.T) {
var schedulerRate iotago.WorkScore = 100000
var protoParams iotago.ProtocolParameters = iotago.NewV3ProtocolParameters(
iotago.WithNetworkOptions(
"xxxNetwork",
Expand Down Expand Up @@ -119,18 +120,20 @@ func TestProtocolParametersJSONMarshalling(t *testing.T) {
20,
24,
),
// TODO: add scheduler rate to increase and decrease threshold expressions. Issue #264
iotago.WithRMCOptions(
iotago.WithCongestionControlOptions(
500,
500,
500,
0.8*10,
0.5*10,
8*schedulerRate, // 0.8*slotDurationInSeconds*schedulerRate
5*schedulerRate, // 0.5*slotDurationInSeconds*schedulerRate
schedulerRate,
1,
100*iotago.MaxBlockSize,
),
iotago.WithVersionSignalingOptions(3, 4, 1),
)

protoParamsJSON := `{"type":0,"version":3,"networkName":"xxxNetwork","bech32Hrp":"xxx","rentStructure":{"vByteCost":6,"vByteFactorData":7,"vByteFactorKey":8,"vByteFactorIssuerKeys":9,"vByteFactorStakingFeature":10},"workScoreStructure":{"dataByte":1,"block":2,"missingParent":3,"input":4,"contextInput":5,"output":6,"nativeToken":7,"staking":8,"blockIssuer":9,"allotment":10,"signatureEd25519":11,"minStrongParentsThreshold":12},"tokenSupply":"1234567890987654321","genesisUnixTimestamp":"1681373293","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"manaGenerationRate":1,"manaGenerationRateExponent":27,"manaDecayFactors":[10,20],"manaDecayFactorsExponent":32,"manaDecayFactorEpochsSum":1337,"manaDecayFactorEpochsSumExponent":20,"stakingUnbondingPeriod":"11","livenessThreshold":"3","minCommittableAge":"10","maxCommittableAge":"20","epochNearingThreshold":"24","rmcParameters":{"rmcMin":"500","increase":"500","decrease":"500","increaseThreshold":8,"decreaseThreshold":5},"versionSignaling":{"windowSize":3,"windowTargetRatio":4,"activationOffset":1}}`
protoParamsJSON := `{"type":0,"version":3,"networkName":"xxxNetwork","bech32Hrp":"xxx","rentStructure":{"vByteCost":6,"vByteFactorData":7,"vByteFactorKey":8,"vByteFactorIssuerKeys":9,"vByteFactorStakingFeature":10},"workScoreStructure":{"dataKilobyte":1,"block":2,"missingParent":3,"input":4,"contextInput":5,"output":6,"nativeToken":7,"staking":8,"blockIssuer":9,"allotment":10,"signatureEd25519":11,"minStrongParentsThreshold":12},"tokenSupply":"1234567890987654321","genesisUnixTimestamp":"1681373293","slotDurationInSeconds":10,"slotsPerEpochExponent":13,"manaGenerationRate":1,"manaGenerationRateExponent":27,"manaDecayFactors":[10,20],"manaDecayFactorsExponent":32,"manaDecayFactorEpochsSum":1337,"manaDecayFactorEpochsSumExponent":20,"stakingUnbondingPeriod":"11","livenessThreshold":"3","minCommittableAge":"10","maxCommittableAge":"20","epochNearingThreshold":"24","congestionControlParameters":{"rmcMin":"500","increase":"500","decrease":"500","increaseThreshold":800000,"decreaseThreshold":500000,"schedulerRate":100000,"minMana":"1","maxBufferSize":3276800},"versionSignaling":{"windowSize":3,"windowTargetRatio":4,"activationOffset":1}}`

jsonProtoParams, err := tpkg.TestAPI.JSONEncode(protoParams)
require.NoError(t, err)
Expand Down
9 changes: 9 additions & 0 deletions api_v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ type v3api struct {
timeProvider *TimeProvider
manaDecayProvider *ManaDecayProvider
livenessThresholdDuration time.Duration
maxBlockWork WorkScore
}

func (v *v3api) JSONEncode(obj any, opts ...serix.Option) ([]byte, error) {
Expand Down Expand Up @@ -216,6 +217,10 @@ func (v *v3api) LivenessThresholdDuration() time.Duration {
return v.livenessThresholdDuration
}

func (v *v3api) MaxBlockWork() WorkScore {
return v.maxBlockWork
}

func (v *v3api) Encode(obj interface{}, opts ...serix.Option) ([]byte, error) {
return v.serixAPI.Encode(context.TODO(), obj, opts...)
}
Expand All @@ -230,13 +235,17 @@ func V3API(protoParams ProtocolParameters) API {

timeProvider := protoParams.TimeProvider()

maxBlockWork, err := protoParams.WorkScoreStructure().MaxBlockWork()
must(err)

//nolint:forcetypeassert // we can safely assume that these are V3ProtocolParameters
v3 := &v3api{
serixAPI: api,
protocolParameters: protoParams.(*V3ProtocolParameters),
timeProvider: timeProvider,
manaDecayProvider: protoParams.ManaDecayProvider(),
livenessThresholdDuration: time.Duration(uint64(protoParams.LivenessThreshold())*uint64(timeProvider.SlotDurationSeconds())) * time.Second,
maxBlockWork: maxBlockWork,
}

must(api.RegisterTypeSettings(TaggedData{},
Expand Down
29 changes: 16 additions & 13 deletions api_v3_protocol_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ type V3ProtocolParameters struct {
}

func NewV3ProtocolParameters(opts ...options.Option[V3ProtocolParameters]) *V3ProtocolParameters {
var schedulerRate WorkScore = 100000
return options.Apply(
new(V3ProtocolParameters),
append([]options.Option[V3ProtocolParameters]{
WithVersion(apiV3Version),
WithNetworkOptions("testnet", PrefixTestnet),
WithSupplyOptions(1813620509061365, 100, 1, 10, 100, 100),
WithWorkScoreOptions(1, 100, 500, 20, 20, 20, 20, 100, 100, 100, 200, 4),
WithWorkScoreOptions(0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
WithTimeProviderOptions(time.Now().Unix(), 10, 13),
// TODO: add sane default values
WithManaOptions(1,
Expand All @@ -34,8 +35,7 @@ func NewV3ProtocolParameters(opts ...options.Option[V3ProtocolParameters]) *V3Pr
0,
),
WithLivenessOptions(3, 10, 20, 24),
// TODO: add Scheduler Rate parameter and include in this expression for increase and decrease thresholds. Issue #264
WithRMCOptions(500, 500, 500, 0.8*10, 0.5*10),
WithCongestionControlOptions(1, 0, 0, 8*schedulerRate, 5*schedulerRate, schedulerRate, 1, 100*MaxBlockSize),
WithStakingOptions(10),
WithVersionSignalingOptions(7, 5, 7),
},
Expand Down Expand Up @@ -103,8 +103,8 @@ func (p *V3ProtocolParameters) EpochNearingThreshold() SlotIndex {
return p.basicProtocolParameters.EpochNearingThreshold
}

func (p *V3ProtocolParameters) RMCParameters() *RMCParameters {
return &p.basicProtocolParameters.RMCParameters
func (p *V3ProtocolParameters) CongestionControlParameters() *CongestionControlParameters {
return &p.basicProtocolParameters.CongestionControlParameters
}

func (p *V3ProtocolParameters) VersionSignaling() *VersionSignaling {
Expand Down Expand Up @@ -169,7 +169,7 @@ func WithSupplyOptions(totalSupply BaseToken, vByteCost uint32, vBFactorData, vB
}

func WithWorkScoreOptions(
dataByte WorkScore,
dataKilobyte WorkScore,
block WorkScore,
missingParent WorkScore,
input WorkScore,
Expand All @@ -183,7 +183,7 @@ func WithWorkScoreOptions(
minStrongParentsThreshold byte) options.Option[V3ProtocolParameters] {
return func(p *V3ProtocolParameters) {
p.basicProtocolParameters.WorkScoreStructure = WorkScoreStructure{
DataByte: dataByte,
DataKilobyte: dataKilobyte,
cyberphysic4l marked this conversation as resolved.
Show resolved Hide resolved
Block: block,
MissingParent: missingParent,
Input: input,
Expand Down Expand Up @@ -227,13 +227,16 @@ func WithLivenessOptions(livenessThreshold SlotIndex, minCommittableAge SlotInde
}
}

func WithRMCOptions(rmcMin Mana, rmcIncrease Mana, rmcDecrease Mana, rmcIncreaseThreshold WorkScore, rmcDecreaseThreshold WorkScore) options.Option[V3ProtocolParameters] {
func WithCongestionControlOptions(rmcMin Mana, rmcIncrease Mana, rmcDecrease Mana, rmcIncreaseThreshold WorkScore, rmcDecreaseThreshold WorkScore, schedulerRate WorkScore, minMana Mana, maxBufferSize uint32) options.Option[V3ProtocolParameters] {
return func(p *V3ProtocolParameters) {
p.basicProtocolParameters.RMCParameters.RMCMin = rmcMin
p.basicProtocolParameters.RMCParameters.Increase = rmcIncrease
p.basicProtocolParameters.RMCParameters.Decrease = rmcDecrease
p.basicProtocolParameters.RMCParameters.IncreaseThreshold = rmcIncreaseThreshold
p.basicProtocolParameters.RMCParameters.DecreaseThreshold = rmcDecreaseThreshold
p.basicProtocolParameters.CongestionControlParameters.RMCMin = rmcMin
p.basicProtocolParameters.CongestionControlParameters.Increase = rmcIncrease
p.basicProtocolParameters.CongestionControlParameters.Decrease = rmcDecrease
p.basicProtocolParameters.CongestionControlParameters.IncreaseThreshold = rmcIncreaseThreshold
p.basicProtocolParameters.CongestionControlParameters.DecreaseThreshold = rmcDecreaseThreshold
p.basicProtocolParameters.CongestionControlParameters.SchedulerRate = schedulerRate
p.basicProtocolParameters.CongestionControlParameters.MinMana = minMana
p.basicProtocolParameters.CongestionControlParameters.MaxBufferSize = maxBufferSize
}
}

Expand Down
81 changes: 54 additions & 27 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,12 @@ func (b *BlockHeader) Hash(api API) (Identifier, error) {
return blake2b.Sum256(headerBytes), nil
}

func (b *BlockHeader) WorkScore(workScoreStructure *WorkScoreStructure) (WorkScore, error) {
// Version, NetworkID, IssuingTime, SlotCommitmentID, LatestFinalisedSlot and IssuerID
return workScoreStructure.DataByte.Multiply(serializer.OneByte +
serializer.UInt64ByteSize +
serializer.UInt64ByteSize +
CommitmentIDLength +
SlotIndexLength +
AccountIDLength)
func (b *BlockHeader) WorkScore(_ *WorkScoreStructure) (WorkScore, error) {
return 0, nil
cyberphysic4l marked this conversation as resolved.
Show resolved Hide resolved
}

func (b *BlockHeader) Size() int {
return BlockHeaderLength
}

type ProtocolBlock struct {
Expand Down Expand Up @@ -279,6 +277,12 @@ func (b *ProtocolBlock) ForEachParent(consumer func(parent Parent)) {
}

func (b *ProtocolBlock) WorkScore(workScoreStructure *WorkScoreStructure) (WorkScore, error) {
workScoreBytes, err := workScoreStructure.DataKilobyte.Multiply(b.Size())
cyberphysic4l marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return 0, err
}
workScoreKilobytes := workScoreBytes / 1024

workScoreHeader, err := b.BlockHeader.WorkScore(workScoreStructure)
if err != nil {
return 0, err
Expand All @@ -294,7 +298,12 @@ func (b *ProtocolBlock) WorkScore(workScoreStructure *WorkScoreStructure) (WorkS
return 0, err
}

return workScoreHeader.Add(workScoreBlock, workScoreSignature)
return workScoreKilobytes.Add(workScoreHeader, workScoreBlock, workScoreSignature)
}

// Size returns the size of the block in bytes.
func (b *ProtocolBlock) Size() int {
return b.BlockHeader.Size() + b.Block.Size() + b.Signature.Size()
}

// syntacticallyValidate syntactically validates the ProtocolBlock.
Expand Down Expand Up @@ -352,6 +361,7 @@ type Block interface {
syntacticallyValidate(api API, protocolBlock *ProtocolBlock) error

ProcessableObject
Sizer
}

// BasicBlock represents a basic vertex in the Tangle/BlockDAG.
Expand Down Expand Up @@ -393,40 +403,48 @@ func (b *BasicBlock) Hash(api API) (Identifier, error) {
}

func (b *BasicBlock) WorkScore(workScoreStructure *WorkScoreStructure) (WorkScore, error) {
// BlockType + BurnedMana
workScoreBytes, err := workScoreStructure.DataByte.Multiply(serializer.OneByte + ManaSize)
if err != nil {
return 0, err
}

// work score for parents is a penalty for each missing strong parent below MinStrongParentsThreshold
var workScoreMissingParents WorkScore
var err error
if len(b.StrongParents) < int(workScoreStructure.MinStrongParentsThreshold) {
var err error
workScoreMissingParents, err = workScoreStructure.MissingParent.Multiply(int(workScoreStructure.MinStrongParentsThreshold) - len(b.StrongParents))
if err != nil {
return 0, err
}
}
var workScorePayload WorkScore
if b.Payload != nil {
workScorePayload, err = b.Payload.WorkScore(workScoreStructure)
if err != nil {
return 0, err
}
}

workScorePayload, err := b.Payload.WorkScore(workScoreStructure)
// offset for block, plus missing parents, plus payload.
return workScoreStructure.Block.Add(workScoreMissingParents, workScorePayload)
}

func (b *BasicBlock) ManaCost(rmc Mana, workScoreStructure *WorkScoreStructure) (Mana, error) {
workScore, err := b.WorkScore(workScoreStructure)
if err != nil {
return 0, err
}

return workScoreBytes.Add(workScoreMissingParents, workScorePayload)
return Mana(workScore) * rmc, nil
}

func (b *BasicBlock) ManaCost(rmc Mana) (Mana, error) {
// workScore, err := blk.protocolBlock.Block.WorkScore(blk.api.ProtocolParameters().WorkScoreStructure())
// if err != nil {
// return 0, err
// }

// return Mana(workScore) * rmc, nil
func (b *BasicBlock) Size() int {
var payloadSize int
if b.Payload != nil {
payloadSize = b.Payload.Size()
}

// TODO: add implement workscore properly with issue #264
return rmc, nil
return serializer.OneByte + // block type
serializer.OneByte + len(b.StrongParents)*SlotIdentifierLength +
serializer.OneByte + len(b.WeakParents)*SlotIdentifierLength +
serializer.OneByte + len(b.ShallowLikeParents)*SlotIdentifierLength +
serializer.UInt32ByteSize + payloadSize + // payload size in serialization + actual payload
ManaSize
}

// syntacticallyValidate syntactically validates the BasicBlock.
Expand Down Expand Up @@ -507,6 +525,15 @@ func (b *ValidationBlock) WorkScore(_ *WorkScoreStructure) (WorkScore, error) {
return 0, nil
}

func (b *ValidationBlock) Size() int {
return serializer.OneByte + // block type
serializer.OneByte + len(b.StrongParents)*SlotIdentifierLength +
serializer.OneByte + len(b.WeakParents)*SlotIdentifierLength +
serializer.OneByte + len(b.ShallowLikeParents)*SlotIdentifierLength +
serializer.OneByte + // highest supported version
IdentifierLength // protocol parameters hash
}

// syntacticallyValidate syntactically validates the ValidationBlock.
func (b *ValidationBlock) syntacticallyValidate(_ API, protocolBlock *ProtocolBlock) error {
if b.HighestSupportedVersion < protocolBlock.ProtocolVersion {
Expand Down
11 changes: 5 additions & 6 deletions block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,30 @@ import (
)

func TestBlock_DeSerialize(t *testing.T) {
// TODO: what does this test actually do?
tests := []deSerializeTest{
{
name: "ok - no payload",
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(1337), tpkg.TestAPI),
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(1337), tpkg.TestAPI, 0),
target: &iotago.ProtocolBlock{},
},
{
name: "ok - transaction",
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(iotago.PayloadTransaction), tpkg.TestAPI),
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(iotago.PayloadTransaction), tpkg.TestAPI, 0),
target: &iotago.ProtocolBlock{},
},
{
name: "ok - milestone",
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(iotago.PayloadMilestone), tpkg.TestAPI),
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(iotago.PayloadMilestone), tpkg.TestAPI, 0),
target: &iotago.ProtocolBlock{},
},
{
name: "ok - tagged data",
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(iotago.PayloadTaggedData), tpkg.TestAPI),
source: tpkg.RandProtocolBlock(tpkg.RandBasicBlock(iotago.PayloadTaggedData), tpkg.TestAPI, 0),
target: &iotago.ProtocolBlock{},
},
{
name: "ok - validation block",
source: tpkg.RandProtocolBlock(tpkg.ValidationBlock(), tpkg.TestAPI),
source: tpkg.RandProtocolBlock(tpkg.ValidationBlock(), tpkg.TestAPI, 0),
target: &iotago.ProtocolBlock{},
},
}
Expand Down
Loading
Loading