-
Notifications
You must be signed in to change notification settings - Fork 95
/
output_delegation.go
224 lines (184 loc) · 7.5 KB
/
output_delegation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package iotago
import (
"golang.org/x/crypto/blake2b"
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/serializer/v2"
"github.com/iotaledger/iota.go/v4/hexutil"
)
const (
// DelegationIDLength is the byte length of a DelegationID.
DelegationIDLength = blake2b.Size256
)
var (
// ErrDelegationCommitmentInputMissing gets returned when no commitment input was passed in a TX containing a Delegation Output.
ErrDelegationCommitmentInputMissing = ierrors.New("delegation output validation requires a commitment input")
// ErrDelegationRewardInputMissing gets returned when no reward input was passed in a TX destroying a Delegation Output.
ErrDelegationRewardInputMissing = ierrors.New("delegation output cannot be destroyed without a reward input")
// ErrDelegationRewardsClaimingInvalid gets returned when it is invalid to claim rewards from a delegation output.
ErrDelegationRewardsClaimingInvalid = ierrors.New("invalid delegation mana rewards claiming")
// ErrDelegationOutputTransitionedTwice gets returned when a delegation output is attempted to be transitioned twice.
ErrDelegationOutputTransitionedTwice = ierrors.New("delegation output attempted to be transitioned twice")
// ErrDelegationModified gets returned when a delegation output's immutable fields are modified.
ErrDelegationModified = ierrors.New("delegated amount, validator ID and start epoch cannot be modified")
// ErrDelegationStartEpochInvalid gets returned when a delegation output's start epoch is not set correctly
// relative to the slot of the current epoch in which the voting power is calculated.
ErrDelegationStartEpochInvalid = ierrors.New("delegation output has invalid start epoch")
// ErrDelegationAmountMismatch gets returned when a delegation output's delegated amount is not equal to the amount.
ErrDelegationAmountMismatch = ierrors.New("delegated amount does not match amount")
// ErrDelegationEndEpochNotZero gets returned when a delegation output's end epoch is not zero at genesis.
ErrDelegationEndEpochNotZero = ierrors.New("end epoch must be set to zero at output genesis")
// ErrDelegationEndEpochInvalid gets returned when a delegation output's end epoch is not set correctly
// relative to the slot of the current epoch in which the voting power is calculated.
ErrDelegationEndEpochInvalid = ierrors.New("delegation end epoch does not match current epoch")
// ErrDelegationValidatorAddressEmpty gets returned when the Validator Address in a Delegation Output is empty.
ErrDelegationValidatorAddressEmpty = ierrors.New("delegation output's validator address is empty")
emptyDelegationID = [DelegationIDLength]byte{}
)
func EmptyDelegationID() DelegationID {
return emptyDelegationID
}
// DelegationID is the identifier for a Delegation Output.
// It is computed as the Blake2b-256 hash of the OutputID of the output which created the Delegation Output.
type DelegationID [DelegationIDLength]byte
// DelegationIDs are DelegationID(s).
type DelegationIDs []DelegationID
func (delegationID DelegationID) Addressable() bool {
return false
}
func (delegationID DelegationID) Empty() bool {
return delegationID == emptyDelegationID
}
func (delegationID DelegationID) ToAddress() ChainAddress {
panic("Delegation ID is not addressable")
}
func (delegationID DelegationID) Matches(other ChainID) bool {
otherDelegationID, isDelegationID := other.(DelegationID)
if !isDelegationID {
return false
}
return delegationID == otherDelegationID
}
func (delegationID DelegationID) String() string {
return hexutil.EncodeHex(delegationID[:])
}
func (delegationID DelegationID) ToHex() string {
return hexutil.EncodeHex(delegationID[:])
}
func (delegationID DelegationID) FromOutputID(outid OutputID) ChainID {
return DelegationIDFromOutputID(outid)
}
// DelegationIDFromOutputID returns the DelegationID computed from a given OutputID.
func DelegationIDFromOutputID(outputID OutputID) DelegationID {
return blake2b.Sum256(outputID[:])
}
type (
DelegationOutputUnlockCondition interface{ UnlockCondition }
DelegationOutputUnlockConditions = UnlockConditions[DelegationOutputUnlockCondition]
)
// DelegationOutput is an output type used to implement delegation.
type DelegationOutput struct {
// The amount of IOTA tokens held by the output.
Amount BaseToken `serix:""`
// The amount of IOTA tokens that were delegated when the output was created.
DelegatedAmount BaseToken `serix:""`
// The identifier for this output.
DelegationID DelegationID `serix:""`
// The Account ID of the validator to which this output is delegating.
ValidatorAddress *AccountAddress `serix:""`
// The index of the first epoch for which this output delegates.
StartEpoch EpochIndex `serix:""`
// The index of the last epoch for which this output delegates.
EndEpoch EpochIndex `serix:""`
// The unlock conditions on this output.
UnlockConditions DelegationOutputUnlockConditions `serix:",omitempty"`
}
func (d *DelegationOutput) Clone() Output {
return &DelegationOutput{
Amount: d.Amount,
DelegatedAmount: d.DelegatedAmount,
DelegationID: d.DelegationID,
ValidatorAddress: d.ValidatorAddress,
StartEpoch: d.StartEpoch,
EndEpoch: d.EndEpoch,
UnlockConditions: d.UnlockConditions.Clone(),
}
}
func (d *DelegationOutput) Equal(other Output) bool {
otherOutput, isSameType := other.(*DelegationOutput)
if !isSameType {
return false
}
if d.Amount != otherOutput.Amount {
return false
}
if d.DelegatedAmount != otherOutput.DelegatedAmount {
return false
}
if d.DelegationID != otherOutput.DelegationID {
return false
}
if !d.ValidatorAddress.Equal(otherOutput.ValidatorAddress) {
return false
}
if d.StartEpoch != otherOutput.StartEpoch {
return false
}
if d.EndEpoch != otherOutput.EndEpoch {
return false
}
if !d.UnlockConditions.Equal(otherOutput.UnlockConditions) {
return false
}
return true
}
func (d *DelegationOutput) Owner() Address {
return d.UnlockConditions.MustSet().Address().Address
}
func (d *DelegationOutput) UnlockableBy(addr Address, pastBoundedSlot SlotIndex, futureBoundedSlot SlotIndex) bool {
ok, _ := outputUnlockableBy(d, nil, addr, pastBoundedSlot, futureBoundedSlot)
return ok
}
func (d *DelegationOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore {
return storageScoreStruct.OffsetOutput +
storageScoreStruct.FactorData().Multiply(StorageScore(d.Size())) +
storageScoreStruct.OffsetDelegation() +
d.UnlockConditions.StorageScore(storageScoreStruct, nil)
}
func (d *DelegationOutput) WorkScore(workScoreParameters *WorkScoreParameters) (WorkScore, error) {
workScoreConditions, err := d.UnlockConditions.WorkScore(workScoreParameters)
if err != nil {
return 0, err
}
return workScoreParameters.Output.Add(workScoreConditions)
}
func (d *DelegationOutput) ChainID() ChainID {
return d.DelegationID
}
func (d *DelegationOutput) FeatureSet() FeatureSet {
return make(FeatureSet, 0)
}
func (d *DelegationOutput) UnlockConditionSet() UnlockConditionSet {
return d.UnlockConditions.MustSet()
}
func (d *DelegationOutput) BaseTokenAmount() BaseToken {
return d.Amount
}
func (d *DelegationOutput) StoredMana() Mana {
return 0
}
func (d *DelegationOutput) Type() OutputType {
return OutputDelegation
}
func (d *DelegationOutput) Size() int {
// OutputType
return serializer.OneByte +
BaseTokenSize +
BaseTokenSize +
DelegationIDLength +
// Account Address Type Byte
serializer.SmallTypeDenotationByteSize +
AccountAddressBytesLength +
EpochIndexLength +
EpochIndexLength +
d.UnlockConditions.Size()
}