github.com/decred/dcrlnd@v0.7.6/watchtower/blob/type.go (about) 1 package blob 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // Flag represents a specify option that can be present in a Type. 9 type Flag uint16 10 11 const ( 12 // FlagReward signals that the justice transaction should contain an 13 // additional output for itself. Signatures sent by the client should 14 // include the reward script negotiated during session creation. Without 15 // the flag, there is only one output sweeping clients funds back to 16 // them solely. 17 FlagReward Flag = 1 18 19 // FlagCommitOutputs signals that the blob contains the information 20 // required to sweep commitment outputs. 21 FlagCommitOutputs Flag = 1 << 1 22 23 // FlagAnchorChannel signals that this blob is meant to spend an anchor 24 // channel, and therefore must expect a P2WSH-style to-remote output if 25 // one exists. 26 FlagAnchorChannel Flag = 1 << 2 27 ) 28 29 // Type returns a Type consisting solely of this flag enabled. 30 func (f Flag) Type() Type { 31 return Type(f) 32 } 33 34 // String returns the name of the flag. 35 func (f Flag) String() string { 36 switch f { 37 case FlagReward: 38 return "FlagReward" 39 case FlagCommitOutputs: 40 return "FlagCommitOutputs" 41 case FlagAnchorChannel: 42 return "FlagAnchorChannel" 43 default: 44 return "FlagUnknown" 45 } 46 } 47 48 // Type is a bit vector composed of Flags that govern various aspects of 49 // reconstructing the justice transaction from an encrypted blob. The flags can 50 // be used to signal behaviors such as which inputs are being swept, which 51 // outputs should be added to the justice transaction, or modify serialization 52 // of the blob itself. 53 type Type uint16 54 55 const ( 56 // TypeAltruistCommit sweeps only commitment outputs to a sweep address 57 // controlled by the user, and does not give the tower a reward. 58 TypeAltruistCommit = Type(FlagCommitOutputs) 59 60 // TypeAltruistAnchorCommit sweeps only commitment outputs from an 61 // anchor commitment to a sweep address controlled by the user, and does 62 // not give the tower a reward. 63 TypeAltruistAnchorCommit = Type(FlagCommitOutputs | FlagAnchorChannel) 64 65 // TypeRewardCommit sweeps only commitment outputs to a sweep address 66 // controlled by the user, and pays a negotiated reward to the tower. 67 TypeRewardCommit = Type(FlagCommitOutputs | FlagReward) 68 ) 69 70 // Has returns true if the Type has the passed flag enabled. 71 func (t Type) Has(flag Flag) bool { 72 return Flag(t)&flag == flag 73 } 74 75 // TypeFromFlags creates a single Type from an arbitrary list of flags. 76 func TypeFromFlags(flags ...Flag) Type { 77 var typ Type 78 for _, flag := range flags { 79 typ |= Type(flag) 80 } 81 82 return typ 83 } 84 85 // IsAnchorChannel returns true if the blob type is for an anchor channel. 86 func (t Type) IsAnchorChannel() bool { 87 return t.Has(FlagAnchorChannel) 88 } 89 90 // knownFlags maps the supported flags to their name. 91 var knownFlags = map[Flag]struct{}{ 92 FlagReward: {}, 93 FlagCommitOutputs: {}, 94 FlagAnchorChannel: {}, 95 } 96 97 // String returns a human readable description of a Type. 98 func (t Type) String() string { 99 var ( 100 hrPieces []string 101 hasUnknownFlags bool 102 ) 103 104 // Iterate through the possible flags from highest to lowest. This will 105 // ensure that the human readable names will be in the same order as the 106 // bits (left to right) if the type were to be printed in big-endian 107 // byte order. 108 for f := Flag(1 << 15); f != 0; f >>= 1 { 109 // If this flag is known, we'll add a human-readable name or its 110 // inverse depending on whether the type has this flag set. 111 if _, ok := knownFlags[f]; ok { 112 if t.Has(f) { 113 hrPieces = append(hrPieces, f.String()) 114 } else { 115 hrPieces = append(hrPieces, "No-"+f.String()) 116 } 117 } else { 118 // Make note of any unknown flags that this type has 119 // set. If any are present, we'll prepend the bit-wise 120 // representation of the type in the final string. 121 if t.Has(f) { 122 hasUnknownFlags = true 123 } 124 } 125 } 126 127 // If there were no unknown flags, we'll simply return the list of human 128 // readable pieces. 129 if !hasUnknownFlags { 130 return fmt.Sprintf("[%s]", strings.Join(hrPieces, "|")) 131 } 132 133 // Otherwise, we'll prepend the bit-wise representation to the human 134 // readable names. 135 return fmt.Sprintf("%016b[%s]", t, strings.Join(hrPieces, "|")) 136 } 137 138 // supportedTypes is the set of all configurations known to be supported by the 139 // package. 140 var supportedTypes = map[Type]struct{}{ 141 TypeAltruistCommit: {}, 142 TypeRewardCommit: {}, 143 TypeAltruistAnchorCommit: {}, 144 } 145 146 // IsSupportedType returns true if the given type is supported by the package. 147 func IsSupportedType(blobType Type) bool { 148 _, ok := supportedTypes[blobType] 149 return ok 150 } 151 152 // SupportedTypes returns a list of all supported blob types. 153 func SupportedTypes() []Type { 154 supported := make([]Type, 0, len(supportedTypes)) 155 for t := range supportedTypes { 156 supported = append(supported, t) 157 } 158 return supported 159 }