github.com/decred/dcrlnd@v0.7.6/feature/manager.go (about)

     1  package feature
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/decred/dcrlnd/lnwire"
     7  )
     8  
     9  // Config houses any runtime modifications to the default set descriptors. For
    10  // our purposes, this typically means disabling certain features to test legacy
    11  // protocol interoperability or functionality.
    12  type Config struct {
    13  	// NoTLVOnion unsets any optional or required TLVOnionPaylod bits from
    14  	// all feature sets.
    15  	NoTLVOnion bool
    16  
    17  	// NoStaticRemoteKey unsets any optional or required StaticRemoteKey
    18  	// bits from all feature sets.
    19  	NoStaticRemoteKey bool
    20  
    21  	// NoAnchors unsets any bits signaling support for anchor outputs.
    22  	NoAnchors bool
    23  
    24  	// NoWumbo unsets any bits signalling support for wumbo channels.
    25  	NoWumbo bool
    26  
    27  	// NoScriptEnforcementLease unsets any bits signaling support for script
    28  	// enforced leases.
    29  	NoScriptEnforcementLease bool
    30  }
    31  
    32  // Manager is responsible for generating feature vectors for different requested
    33  // feature sets.
    34  type Manager struct {
    35  	// fsets is a static map of feature set to raw feature vectors. Requests
    36  	// are fulfilled by cloning these interal feature vectors.
    37  	fsets map[Set]*lnwire.RawFeatureVector
    38  }
    39  
    40  // NewManager creates a new feature Manager, applying any custom modifications
    41  // to its feature sets before returning.
    42  func NewManager(cfg Config) (*Manager, error) {
    43  	return newManager(cfg, defaultSetDesc)
    44  }
    45  
    46  // newManager creates a new feature Manager, applying any custom modifications
    47  // to its feature sets before returning. This method accepts the setDesc as its
    48  // own parameter so that it can be unit tested.
    49  func newManager(cfg Config, desc setDesc) (*Manager, error) {
    50  	// First build the default feature vector for all known sets.
    51  	fsets := make(map[Set]*lnwire.RawFeatureVector)
    52  	for bit, sets := range desc {
    53  		for set := range sets {
    54  			// Fetch the feature vector for this set, allocating a
    55  			// new one if it doesn't exist.
    56  			fv, ok := fsets[set]
    57  			if !ok {
    58  				fv = lnwire.NewRawFeatureVector()
    59  			}
    60  
    61  			// Set the configured bit on the feature vector,
    62  			// ensuring that we don't set two feature bits for the
    63  			// same pair.
    64  			err := fv.SafeSet(bit)
    65  			if err != nil {
    66  				return nil, fmt.Errorf("unable to set "+
    67  					"%v in %v: %v", bit, set, err)
    68  			}
    69  
    70  			// Write the updated feature vector under its set.
    71  			fsets[set] = fv
    72  		}
    73  	}
    74  
    75  	// Now, remove any features as directed by the config.
    76  	for set, raw := range fsets {
    77  		if cfg.NoTLVOnion {
    78  			raw.Unset(lnwire.TLVOnionPayloadOptional)
    79  			raw.Unset(lnwire.TLVOnionPayloadRequired)
    80  			raw.Unset(lnwire.PaymentAddrOptional)
    81  			raw.Unset(lnwire.PaymentAddrRequired)
    82  			raw.Unset(lnwire.MPPOptional)
    83  			raw.Unset(lnwire.MPPRequired)
    84  			raw.Unset(lnwire.AMPOptional)
    85  			raw.Unset(lnwire.AMPRequired)
    86  		}
    87  		if cfg.NoStaticRemoteKey {
    88  			raw.Unset(lnwire.StaticRemoteKeyOptional)
    89  			raw.Unset(lnwire.StaticRemoteKeyRequired)
    90  		}
    91  		if cfg.NoAnchors {
    92  			raw.Unset(lnwire.AnchorsZeroFeeHtlcTxOptional)
    93  			raw.Unset(lnwire.AnchorsZeroFeeHtlcTxRequired)
    94  
    95  			// If anchors are disabled, then we also need to
    96  			// disable all other features that depend on it as
    97  			// well, as otherwise we may create an invalid feature
    98  			// bit set.
    99  			for bit, depFeatures := range deps {
   100  				for depFeature := range depFeatures {
   101  					switch {
   102  					case depFeature == lnwire.AnchorsZeroFeeHtlcTxRequired:
   103  						fallthrough
   104  					case depFeature == lnwire.AnchorsZeroFeeHtlcTxOptional:
   105  						raw.Unset(bit)
   106  					}
   107  				}
   108  			}
   109  		}
   110  		if cfg.NoWumbo {
   111  			raw.Unset(lnwire.WumboChannelsOptional)
   112  			raw.Unset(lnwire.WumboChannelsRequired)
   113  		}
   114  		if cfg.NoScriptEnforcementLease {
   115  			raw.Unset(lnwire.ScriptEnforcedLeaseOptional)
   116  			raw.Unset(lnwire.ScriptEnforcedLeaseRequired)
   117  		}
   118  
   119  		// Ensure that all of our feature sets properly set any
   120  		// dependent features.
   121  		fv := lnwire.NewFeatureVector(raw, lnwire.Features)
   122  		err := ValidateDeps(fv)
   123  		if err != nil {
   124  			return nil, fmt.Errorf("invalid feature set %v: %v",
   125  				set, err)
   126  		}
   127  	}
   128  
   129  	return &Manager{
   130  		fsets: fsets,
   131  	}, nil
   132  }
   133  
   134  // GetRaw returns a raw feature vector for the passed set. If no set is known,
   135  // an empty raw feature vector is returned.
   136  func (m *Manager) GetRaw(set Set) *lnwire.RawFeatureVector {
   137  	if fv, ok := m.fsets[set]; ok {
   138  		return fv.Clone()
   139  	}
   140  
   141  	return lnwire.NewRawFeatureVector()
   142  }
   143  
   144  // Get returns a feature vector for the passed set. If no set is known, an empty
   145  // feature vector is returned.
   146  func (m *Manager) Get(set Set) *lnwire.FeatureVector {
   147  	raw := m.GetRaw(set)
   148  	return lnwire.NewFeatureVector(raw, lnwire.Features)
   149  }
   150  
   151  // ListSets returns a list of the feature sets that our node supports.
   152  func (m *Manager) ListSets() []Set {
   153  	var sets []Set
   154  
   155  	for set := range m.fsets {
   156  		sets = append(sets, set)
   157  	}
   158  
   159  	return sets
   160  }