muun-recovery/vendor/github.com/muun/libwallet/features.go

140 lines
3.6 KiB
Go

package libwallet
import (
"fmt"
)
const (
BackendFeatureTaproot = "TAPROOT"
BackendFeatureTaprootPreactivation = "TAPROOT_PREACTIVATION"
UserActivatedFeatureStatusOff = "off"
UserActivatedFeatureStatusCanPreactivate = "can_preactivate"
UserActivatedFeatureStatusCanActivate = "can_activate"
UserActivatedFeatureStatusPreactivated = "preactivated"
UserActivatedFeatureStatusScheduledActivation = "scheduled_activation"
UserActivatedFeatureStatusActive = "active"
)
var UserActivatedFeatureTaproot UserActivatedFeature = &taprootUserActivatedFeature{}
type UserActivatedFeature interface {
Blockheight(*Network) int
RequiredKitVersion() int
BackendFeature() string
BackendPreactivationFeature() string
}
type taprootUserActivatedFeature struct {}
func (t *taprootUserActivatedFeature) Blockheight(network *Network) int {
switch network.Name() {
case Mainnet().Name():
// 709_632 is defined in the BIP and we use a 6 block safety margin
return 709_632 + 6
case Regtest().Name():
// A nice low value for testing
return 100
case Testnet().Name():
// A nice low value for testing
return 100
}
panic(fmt.Sprintf("Unexpected network: %v", network.Name()))
}
func (t *taprootUserActivatedFeature) RequiredKitVersion() int {
return EKVersionMusig
}
func (t *taprootUserActivatedFeature) BackendFeature() string {
return BackendFeatureTaproot
}
func (t *taprootUserActivatedFeature) BackendPreactivationFeature() string {
return BackendFeatureTaprootPreactivation
}
func DetermineUserActivatedFeatureStatus(
feature UserActivatedFeature,
blockHeight int,
exportedKitVersions *IntList,
backendFeatures *StringList,
network *Network,
) string {
// If the feature is turned off by houston, two things can happen:
// 1. The (pre)activation event is not enabled: ie kill switch
// 2. Activation is held-off and the status is frozen as if the network
// never activated.: ie backend feature toggle
if len(feature.BackendFeature()) > 0 &&
!backendFeatures.Contains(feature.BackendPreactivationFeature()) {
return UserActivatedFeatureStatusOff
}
activatedByHouston := len(feature.BackendFeature()) > 0 &&
backendFeatures.Contains(feature.BackendFeature())
activatedByNetwork := blockHeight >= feature.Blockheight(network)
// If the user never exported a kit, they have the feature implicitly active
if exportedKitVersions.Length() == 0 {
if activatedByNetwork && activatedByHouston {
return UserActivatedFeatureStatusActive
} else if activatedByHouston {
return UserActivatedFeatureStatusScheduledActivation
} else {
return UserActivatedFeatureStatusOff
}
}
var maxKitVersion int
for i := 0; i < exportedKitVersions.Length(); i++ {
if exportedKitVersions.Get(i) > maxKitVersion {
maxKitVersion = exportedKitVersions.Get(i)
}
}
if maxKitVersion >= feature.RequiredKitVersion() {
// If the user activated already, it's up to the network
if activatedByNetwork && activatedByHouston {
return UserActivatedFeatureStatusActive
} else if exportedKitVersions.Length() > 1 {
// If the user had pre-existing kits, then they updated
return UserActivatedFeatureStatusPreactivated
} else {
// Otherwise they just happened to export during the activation
return UserActivatedFeatureStatusScheduledActivation
}
} else {
// Otherwise it's up to the user
if !activatedByHouston {
return UserActivatedFeatureStatusOff
} else if activatedByNetwork {
return UserActivatedFeatureStatusCanActivate
} else {
return UserActivatedFeatureStatusCanPreactivate
}
}
}