github.com/decred/dcrlnd@v0.7.6/netann/channel_update_test.go (about)

     1  package netann_test
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
     9  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
    10  	"github.com/decred/dcrlnd/keychain"
    11  	"github.com/decred/dcrlnd/lnwallet"
    12  	"github.com/decred/dcrlnd/lnwire"
    13  	"github.com/decred/dcrlnd/netann"
    14  	"github.com/decred/dcrlnd/routing"
    15  )
    16  
    17  type mockSigner struct {
    18  	err error
    19  }
    20  
    21  func (m *mockSigner) SignMessage(_ keychain.KeyLocator,
    22  	_ []byte, _ bool) (*ecdsa.Signature, error) {
    23  
    24  	if m.err != nil {
    25  		return nil, m.err
    26  	}
    27  
    28  	return nil, nil
    29  }
    30  
    31  var _ lnwallet.MessageSigner = (*mockSigner)(nil)
    32  
    33  var (
    34  	privKey, _    = secp256k1.GeneratePrivateKey()
    35  	privKeySigner = keychain.NewPrivKeyMessageSigner(privKey, testKeyLoc)
    36  
    37  	pubKey = privKey.PubKey()
    38  
    39  	errFailedToSign = errors.New("unable to sign message")
    40  )
    41  
    42  type updateDisableTest struct {
    43  	name         string
    44  	startEnabled bool
    45  	disable      bool
    46  	startTime    time.Time
    47  	signer       lnwallet.MessageSigner
    48  	expErr       error
    49  }
    50  
    51  var updateDisableTests = []updateDisableTest{
    52  	{
    53  		name:         "working signer enabled to disabled",
    54  		startEnabled: true,
    55  		disable:      true,
    56  		startTime:    time.Now(),
    57  		signer:       netann.NewNodeSigner(privKeySigner),
    58  	},
    59  	{
    60  		name:         "working signer enabled to enabled",
    61  		startEnabled: true,
    62  		disable:      false,
    63  		startTime:    time.Now(),
    64  		signer:       netann.NewNodeSigner(privKeySigner),
    65  	},
    66  	{
    67  		name:         "working signer disabled to enabled",
    68  		startEnabled: false,
    69  		disable:      false,
    70  		startTime:    time.Now(),
    71  		signer:       netann.NewNodeSigner(privKeySigner),
    72  	},
    73  	{
    74  		name:         "working signer disabled to disabled",
    75  		startEnabled: false,
    76  		disable:      true,
    77  		startTime:    time.Now(),
    78  		signer:       netann.NewNodeSigner(privKeySigner),
    79  	},
    80  	{
    81  		name:         "working signer future monotonicity",
    82  		startEnabled: true,
    83  		disable:      true,
    84  		startTime:    time.Now().Add(time.Hour), // must increment
    85  		signer:       netann.NewNodeSigner(privKeySigner),
    86  	},
    87  	{
    88  		name:      "failing signer",
    89  		startTime: time.Now(),
    90  		signer:    &mockSigner{err: errFailedToSign},
    91  		expErr:    errFailedToSign,
    92  	},
    93  	{
    94  		name:      "invalid sig from signer",
    95  		startTime: time.Now(),
    96  		signer:    &mockSigner{}, // returns a nil signature
    97  		expErr:    errors.New("cannot decode empty signature"),
    98  	},
    99  }
   100  
   101  // TestUpdateDisableFlag checks the behavior of UpdateDisableFlag, asserting
   102  // that the proper channel flags are set, the timestamp always increases
   103  // monotonically, and that the correct errors are returned in the event that the
   104  // signer is unable to produce a signature.
   105  func TestUpdateDisableFlag(t *testing.T) {
   106  	t.Parallel()
   107  
   108  	for _, tc := range updateDisableTests {
   109  		tc := tc
   110  		t.Run(tc.name, func(t *testing.T) {
   111  			// Create the initial update, the only fields we are
   112  			// concerned with in this test are the timestamp and the
   113  			// channel flags.
   114  			ogUpdate := &lnwire.ChannelUpdate{
   115  				Timestamp: uint32(tc.startTime.Unix()),
   116  			}
   117  			if !tc.startEnabled {
   118  				ogUpdate.ChannelFlags |= lnwire.ChanUpdateDisabled
   119  			}
   120  
   121  			// Create new update to sign using the same fields as
   122  			// the original. UpdateDisableFlag will mutate the
   123  			// passed channel update, so we keep the old one to test
   124  			// against.
   125  			newUpdate := &lnwire.ChannelUpdate{
   126  				Timestamp:    ogUpdate.Timestamp,
   127  				ChannelFlags: ogUpdate.ChannelFlags,
   128  			}
   129  
   130  			// Attempt to update and sign the new update, specifying
   131  			// disabled or enabled as prescribed in the test case.
   132  			err := netann.SignChannelUpdate(
   133  				tc.signer, testKeyLoc, newUpdate,
   134  				netann.ChanUpdSetDisable(tc.disable),
   135  				netann.ChanUpdSetTimestamp,
   136  			)
   137  
   138  			var fail bool
   139  			switch {
   140  
   141  			// Both nil, pass.
   142  			case tc.expErr == nil && err == nil:
   143  
   144  			// Both non-nil, compare error strings since some
   145  			// methods don't return concrete error types.
   146  			case tc.expErr != nil && err != nil:
   147  				if err.Error() != tc.expErr.Error() {
   148  					fail = true
   149  				}
   150  
   151  			// Otherwise, one is nil and one is non-nil.
   152  			default:
   153  				fail = true
   154  			}
   155  
   156  			if fail {
   157  				t.Fatalf("expected error: %v, got %v",
   158  					tc.expErr, err)
   159  			}
   160  
   161  			// Exit early if the test expected a failure.
   162  			if tc.expErr != nil {
   163  				return
   164  			}
   165  
   166  			// Verify that the timestamp has increased from the
   167  			// original update.
   168  			if newUpdate.Timestamp <= ogUpdate.Timestamp {
   169  				t.Fatalf("update timestamp should be "+
   170  					"monotonically increasing, "+
   171  					"original: %d, new %d",
   172  					ogUpdate.Timestamp, newUpdate.Timestamp)
   173  			}
   174  
   175  			// Verify that the disabled flag is properly set.
   176  			disabled := newUpdate.ChannelFlags&
   177  				lnwire.ChanUpdateDisabled != 0
   178  			if disabled != tc.disable {
   179  				t.Fatalf("expected disable:%v, found:%v",
   180  					tc.disable, disabled)
   181  			}
   182  
   183  			// Finally, validate the signature using the router's
   184  			// verification logic.
   185  			err = routing.ValidateChannelUpdateAnn(
   186  				pubKey, 0, newUpdate,
   187  			)
   188  			if err != nil {
   189  				t.Fatalf("channel update failed to "+
   190  					"validate: %v", err)
   191  			}
   192  		})
   193  	}
   194  }