/
rotate.go
70 lines (62 loc) · 2.45 KB
/
rotate.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
package transaction
import (
"errors"
"fmt"
iotago "github.com/iotaledger/iota.go/v3"
"github.com/iotaledger/wasp/packages/cryptolib"
"github.com/iotaledger/wasp/packages/parameters"
"github.com/iotaledger/wasp/packages/util"
)
func NewRotateChainStateControllerTx(
aliasID iotago.AliasID,
newStateController iotago.Address,
chainOutputID iotago.OutputID,
chainOutput iotago.Output,
kp cryptolib.VariantKeyPair,
) (*iotago.Transaction, error) {
o, ok := chainOutput.(*iotago.AliasOutput)
if !ok {
return nil, fmt.Errorf("provided output is not the correct one. Expected AliasOutput, received %T=%v", chainOutput, chainOutput)
}
resolvedAliasID := util.AliasIDFromAliasOutput(o, chainOutputID)
if resolvedAliasID != aliasID {
return nil, fmt.Errorf("provided output is not the correct one. Expected ChainID: %s, got: %s",
aliasID.ToAddress().Bech32(parameters.L1().Protocol.Bech32HRP),
chainOutput.(*iotago.AliasOutput).AliasID.ToAddress().Bech32(parameters.L1().Protocol.Bech32HRP),
)
}
// create a TX with that UTXO as input, and the updated addr unlock condition on the new output
inputIDs := iotago.OutputIDs{chainOutputID}
outSet := iotago.OutputSet{}
outSet[chainOutputID] = chainOutput
inputsCommitment := inputIDs.OrderedSet(outSet).MustCommitment()
newChainOutput := chainOutput.Clone().(*iotago.AliasOutput)
newChainOutput.AliasID = resolvedAliasID
oldUnlockConditions := newChainOutput.UnlockConditionSet()
newChainOutput.Conditions = make(iotago.UnlockConditions, len(oldUnlockConditions))
// update the unlock conditions to the new state controller
i := 0
for t, condition := range oldUnlockConditions {
newChainOutput.Conditions[i] = condition.Clone()
if t == iotago.UnlockConditionStateControllerAddress {
// found the condition to alter
c, ok := newChainOutput.Conditions[i].(*iotago.StateControllerAddressUnlockCondition)
if !ok {
return nil, errors.New("unexpected error trying to get StateControllerAddressUnlockCondition")
}
c.Address = newStateController
newChainOutput.Conditions[i] = c.Clone()
}
i++
}
// remove any "sender feature"
var newFeatures iotago.Features
for t, feature := range chainOutput.FeatureSet() {
if t != iotago.FeatureSender {
newFeatures = append(newFeatures, feature)
}
}
newChainOutput.Features = newFeatures
outputs := iotago.Outputs{newChainOutput}
return CreateAndSignTx(inputIDs.UTXOInputs(), inputsCommitment, outputs, kp, parameters.L1().Protocol.NetworkID())
}