-
Notifications
You must be signed in to change notification settings - Fork 95
/
output_anchor.go
197 lines (164 loc) · 5.72 KB
/
output_anchor.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
package iotago
import (
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/serializer/v2"
)
var (
// ErrAnchorInvalidStateTransition gets returned when an anchor is doing an invalid state transition.
ErrAnchorInvalidStateTransition = ierrors.New("invalid anchor state transition")
// ErrAnchorInvalidGovernanceTransition gets returned when an anchor is doing an invalid governance transition.
ErrAnchorInvalidGovernanceTransition = ierrors.New("invalid anchor governance transition")
// ErrAnchorMissing gets returned when an anchor is missing.
ErrAnchorMissing = ierrors.New("anchor is missing")
)
type (
AnchorOutputUnlockCondition interface{ UnlockCondition }
AnchorOutputFeature interface{ Feature }
AnchorOutputImmFeature interface{ Feature }
AnchorOutputUnlockConditions = UnlockConditions[AnchorOutputUnlockCondition]
AnchorOutputFeatures = Features[AnchorOutputFeature]
AnchorOutputImmFeatures = Features[AnchorOutputImmFeature]
)
// AnchorOutput is an output type which represents an anchor.
type AnchorOutput struct {
// The amount of IOTA tokens held by the output.
Amount BaseToken `serix:""`
// The stored mana held by the output.
Mana Mana `serix:""`
// The identifier for this anchor.
AnchorID AnchorID `serix:""`
// The index of the state.
StateIndex uint32 `serix:""`
// The unlock conditions on this output.
UnlockConditions AnchorOutputUnlockConditions `serix:",omitempty"`
// The features on the output.
Features AnchorOutputFeatures `serix:",omitempty"`
// The immutable feature on the output.
ImmutableFeatures AnchorOutputImmFeatures `serix:",omitempty"`
}
func (a *AnchorOutput) GovernorAddress() Address {
return a.UnlockConditions.MustSet().GovernorAddress().Address
}
func (a *AnchorOutput) StateController() Address {
return a.UnlockConditions.MustSet().StateControllerAddress().Address
}
func (a *AnchorOutput) Clone() Output {
return &AnchorOutput{
Amount: a.Amount,
Mana: a.Mana,
AnchorID: a.AnchorID,
StateIndex: a.StateIndex,
UnlockConditions: a.UnlockConditions.Clone(),
Features: a.Features.Clone(),
ImmutableFeatures: a.ImmutableFeatures.Clone(),
}
}
func (a *AnchorOutput) Equal(other Output) bool {
otherOutput, isSameType := other.(*AnchorOutput)
if !isSameType {
return false
}
if a.Amount != otherOutput.Amount {
return false
}
if a.Mana != otherOutput.Mana {
return false
}
if a.AnchorID != otherOutput.AnchorID {
return false
}
if a.StateIndex != otherOutput.StateIndex {
return false
}
if !a.UnlockConditions.Equal(otherOutput.UnlockConditions) {
return false
}
if !a.Features.Equal(otherOutput.Features) {
return false
}
if !a.ImmutableFeatures.Equal(otherOutput.ImmutableFeatures) {
return false
}
return true
}
func (a *AnchorOutput) UnlockableBy(addr Address, next OwnerTransitionDependentOutput, pastBoundedSlotIndex SlotIndex, futureBoundedSlotIndex SlotIndex) (bool, error) {
return outputUnlockableBy(a, next, addr, pastBoundedSlotIndex, futureBoundedSlotIndex)
}
func (a *AnchorOutput) StorageScore(storageScoreStruct *StorageScoreStructure, _ StorageScoreFunc) StorageScore {
return storageScoreStruct.OffsetOutput +
storageScoreStruct.FactorData().Multiply(StorageScore(a.Size())) +
a.UnlockConditions.StorageScore(storageScoreStruct, nil) +
a.Features.StorageScore(storageScoreStruct, nil) +
a.ImmutableFeatures.StorageScore(storageScoreStruct, nil)
}
func (a *AnchorOutput) WorkScore(workScoreParameters *WorkScoreParameters) (WorkScore, error) {
workScoreConditions, err := a.UnlockConditions.WorkScore(workScoreParameters)
if err != nil {
return 0, err
}
workScoreFeatures, err := a.Features.WorkScore(workScoreParameters)
if err != nil {
return 0, err
}
workScoreImmutableFeatures, err := a.ImmutableFeatures.WorkScore(workScoreParameters)
if err != nil {
return 0, err
}
return workScoreParameters.Output.Add(workScoreConditions, workScoreFeatures, workScoreImmutableFeatures)
}
func (a *AnchorOutput) Owner(nextState OwnerTransitionDependentOutput) (Address, error) {
// if there isn't a next state, then only the governance address can destroy the anchor
if nextState == nil {
return a.GovernorAddress(), nil
}
otherAnchorOutput, isAnchorOutput := nextState.(*AnchorOutput)
if !isAnchorOutput {
return nil, ierrors.WithMessagef(ErrOwnerTransitionDependentOutputNextInvalid, "expected AnchorOutput but got %s for owner computation", nextState.Type())
}
switch {
case a.StateIndex == otherAnchorOutput.StateIndex:
return a.GovernorAddress(), nil
case a.StateIndex+1 == otherAnchorOutput.StateIndex:
return a.StateController(), nil
default:
return nil, ierrors.WithMessage(ErrOwnerTransitionDependentOutputNextInvalid, "can not compute right owner for anchor output as state index delta is invalid")
}
}
func (a *AnchorOutput) ChainID() ChainID {
return a.AnchorID
}
func (a *AnchorOutput) FeatureSet() FeatureSet {
return a.Features.MustSet()
}
func (a *AnchorOutput) UnlockConditionSet() UnlockConditionSet {
return a.UnlockConditions.MustSet()
}
func (a *AnchorOutput) ImmutableFeatureSet() FeatureSet {
return a.ImmutableFeatures.MustSet()
}
func (a *AnchorOutput) BaseTokenAmount() BaseToken {
return a.Amount
}
func (a *AnchorOutput) StoredMana() Mana {
return a.Mana
}
func (a *AnchorOutput) Target() (Address, error) {
addr := new(AnchorAddress)
copy(addr[:], a.AnchorID[:])
return addr, nil
}
func (a *AnchorOutput) Type() OutputType {
return OutputAnchor
}
func (a *AnchorOutput) Size() int {
// OutputType
return serializer.OneByte +
BaseTokenSize +
ManaSize +
AnchorIDLength +
// StateIndex
serializer.UInt32ByteSize +
a.UnlockConditions.Size() +
a.Features.Size() +
a.ImmutableFeatures.Size()
}