github.com/decred/dcrlnd@v0.7.6/chanbackup/single_test.go (about)

     1  package chanbackup
     2  
     3  import (
     4  	"bytes"
     5  	"math"
     6  	"math/rand"
     7  	"net"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/davecgh/go-spew/spew"
    12  	"github.com/decred/dcrd/chaincfg/chainhash"
    13  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    14  	"github.com/decred/dcrd/wire"
    15  	"github.com/decred/dcrlnd/channeldb"
    16  	"github.com/decred/dcrlnd/keychain"
    17  	"github.com/decred/dcrlnd/lnwire"
    18  	"github.com/decred/dcrlnd/shachain"
    19  )
    20  
    21  var (
    22  	chainHash = chainhash.Hash{
    23  		0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
    24  		0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
    25  		0x4f, 0x2f, 0x6f, 0x25, 0x18, 0xa3, 0xef, 0xb9,
    26  		0x64, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
    27  	}
    28  
    29  	op = wire.OutPoint{
    30  		Hash:  chainHash,
    31  		Index: 4,
    32  	}
    33  
    34  	addr1, _ = net.ResolveTCPAddr("tcp", "10.0.0.2:9000")
    35  	addr2, _ = net.ResolveTCPAddr("tcp", "10.0.0.3:9000")
    36  )
    37  
    38  func assertSingleEqual(t *testing.T, a, b Single) {
    39  	t.Helper()
    40  
    41  	if a.Version != b.Version {
    42  		t.Fatalf("versions don't match: %v vs %v", a.Version,
    43  			b.Version)
    44  	}
    45  	if a.IsInitiator != b.IsInitiator {
    46  		t.Fatalf("initiators don't match: %v vs %v", a.IsInitiator,
    47  			b.IsInitiator)
    48  	}
    49  	if a.ChainHash != b.ChainHash {
    50  		t.Fatalf("chainhash doesn't match: %v vs %v", a.ChainHash,
    51  			b.ChainHash)
    52  	}
    53  	if a.FundingOutpoint != b.FundingOutpoint {
    54  		t.Fatalf("chan point doesn't match: %v vs %v",
    55  			a.FundingOutpoint, b.FundingOutpoint)
    56  	}
    57  	if a.ShortChannelID != b.ShortChannelID {
    58  		t.Fatalf("chan id doesn't match: %v vs %v",
    59  			a.ShortChannelID, b.ShortChannelID)
    60  	}
    61  	if a.Capacity != b.Capacity {
    62  		t.Fatalf("capacity doesn't match: %v vs %v",
    63  			a.Capacity, b.Capacity)
    64  	}
    65  	if !a.RemoteNodePub.IsEqual(b.RemoteNodePub) {
    66  		t.Fatalf("node pubs don't match %x vs %x",
    67  			a.RemoteNodePub.SerializeCompressed(),
    68  			b.RemoteNodePub.SerializeCompressed())
    69  	}
    70  	if !reflect.DeepEqual(a.LocalChanCfg, b.LocalChanCfg) {
    71  		t.Fatalf("local chan config doesn't match: %v vs %v",
    72  			spew.Sdump(a.LocalChanCfg),
    73  			spew.Sdump(b.LocalChanCfg))
    74  	}
    75  	if !reflect.DeepEqual(a.RemoteChanCfg, b.RemoteChanCfg) {
    76  		t.Fatalf("remote chan config doesn't match: %v vs %v",
    77  			spew.Sdump(a.RemoteChanCfg),
    78  			spew.Sdump(b.RemoteChanCfg))
    79  	}
    80  	if !reflect.DeepEqual(a.ShaChainRootDesc, b.ShaChainRootDesc) {
    81  		t.Fatalf("sha chain point doesn't match: %v vs %v",
    82  			spew.Sdump(a.ShaChainRootDesc),
    83  			spew.Sdump(b.ShaChainRootDesc))
    84  	}
    85  
    86  	if len(a.Addresses) != len(b.Addresses) {
    87  		t.Fatalf("expected %v addrs got %v", len(a.Addresses),
    88  			len(b.Addresses))
    89  	}
    90  	for i := 0; i < len(a.Addresses); i++ {
    91  		if a.Addresses[i].String() != b.Addresses[i].String() {
    92  			t.Fatalf("addr mismatch: %v vs %v",
    93  				a.Addresses[i], b.Addresses[i])
    94  		}
    95  	}
    96  }
    97  
    98  func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
    99  	var testPriv [32]byte
   100  	if _, err := rand.Read(testPriv[:]); err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	pub := secp256k1.PrivKeyFromBytes(testPriv[:]).PubKey()
   105  
   106  	var chanPoint wire.OutPoint
   107  	if _, err := rand.Read(chanPoint.Hash[:]); err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	chanPoint.Index = uint32(rand.Intn(math.MaxUint16))
   112  
   113  	var shaChainRoot [32]byte
   114  	if _, err := rand.Read(shaChainRoot[:]); err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	shaChainProducer := shachain.NewRevocationProducer(shaChainRoot)
   119  
   120  	var isInitiator bool
   121  	if rand.Int63()%2 == 0 {
   122  		isInitiator = true
   123  	}
   124  
   125  	chanType := channeldb.ChannelType(rand.Intn(8))
   126  
   127  	return &channeldb.OpenChannel{
   128  		ChainHash:       chainHash,
   129  		ChanType:        chanType,
   130  		IsInitiator:     isInitiator,
   131  		FundingOutpoint: chanPoint,
   132  		ShortChannelID: lnwire.NewShortChanIDFromInt(
   133  			uint64(rand.Int63()),
   134  		),
   135  		ThawHeight:  rand.Uint32(),
   136  		IdentityPub: pub,
   137  		LocalChanCfg: channeldb.ChannelConfig{
   138  			ChannelConstraints: channeldb.ChannelConstraints{
   139  				CsvDelay: uint16(rand.Int63()),
   140  			},
   141  			MultiSigKey: keychain.KeyDescriptor{
   142  				KeyLocator: keychain.KeyLocator{
   143  					Family: keychain.KeyFamily(rand.Int63()),
   144  					Index:  uint32(rand.Int63()),
   145  				},
   146  			},
   147  			RevocationBasePoint: keychain.KeyDescriptor{
   148  				KeyLocator: keychain.KeyLocator{
   149  					Family: keychain.KeyFamily(rand.Int63()),
   150  					Index:  uint32(rand.Int63()),
   151  				},
   152  			},
   153  			PaymentBasePoint: keychain.KeyDescriptor{
   154  				KeyLocator: keychain.KeyLocator{
   155  					Family: keychain.KeyFamily(rand.Int63()),
   156  					Index:  uint32(rand.Int63()),
   157  				},
   158  			},
   159  			DelayBasePoint: keychain.KeyDescriptor{
   160  				KeyLocator: keychain.KeyLocator{
   161  					Family: keychain.KeyFamily(rand.Int63()),
   162  					Index:  uint32(rand.Int63()),
   163  				},
   164  			},
   165  			HtlcBasePoint: keychain.KeyDescriptor{
   166  				KeyLocator: keychain.KeyLocator{
   167  					Family: keychain.KeyFamily(rand.Int63()),
   168  					Index:  uint32(rand.Int63()),
   169  				},
   170  			},
   171  		},
   172  		RemoteChanCfg: channeldb.ChannelConfig{
   173  			ChannelConstraints: channeldb.ChannelConstraints{
   174  				CsvDelay: uint16(rand.Int63()),
   175  			},
   176  			MultiSigKey: keychain.KeyDescriptor{
   177  				PubKey: pub,
   178  			},
   179  			RevocationBasePoint: keychain.KeyDescriptor{
   180  				PubKey: pub,
   181  			},
   182  			PaymentBasePoint: keychain.KeyDescriptor{
   183  				PubKey: pub,
   184  			},
   185  			DelayBasePoint: keychain.KeyDescriptor{
   186  				PubKey: pub,
   187  			},
   188  			HtlcBasePoint: keychain.KeyDescriptor{
   189  				PubKey: pub,
   190  			},
   191  		},
   192  		RevocationProducer: shaChainProducer,
   193  	}, nil
   194  }
   195  
   196  // TestSinglePackUnpack tests that we're able to unpack a previously packed
   197  // channel backup.
   198  func TestSinglePackUnpack(t *testing.T) {
   199  	t.Parallel()
   200  
   201  	// Given our test pub key, we'll create an open channel shell that
   202  	// contains all the information we need to create a static channel
   203  	// backup.
   204  	channel, err := genRandomOpenChannelShell()
   205  	if err != nil {
   206  		t.Fatalf("unable to gen open channel: %v", err)
   207  	}
   208  
   209  	singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2})
   210  
   211  	keyRing := &mockKeyRing{}
   212  
   213  	versionTestCases := []struct {
   214  		// version is the pack/unpack version that we should use to
   215  		// decode/encode the final SCB.
   216  		version SingleBackupVersion
   217  
   218  		// valid tests us if this test case should pass or not.
   219  		valid bool
   220  	}{
   221  		// The default version, should pack/unpack with no problem.
   222  		{
   223  			version: DefaultSingleVersion,
   224  			valid:   true,
   225  		},
   226  
   227  		// The new tweakless version, should pack/unpack with no
   228  		// problem.
   229  		{
   230  			version: TweaklessCommitVersion,
   231  			valid:   true,
   232  		},
   233  
   234  		// The new anchor version, should pack/unpack with no
   235  		// problem.
   236  		{
   237  			version: AnchorsCommitVersion,
   238  			valid:   true,
   239  		},
   240  
   241  		// The new script enforced channel lease version should
   242  		// pack/unpack with no problem.
   243  		{
   244  			version: ScriptEnforcedLeaseVersion,
   245  			valid:   true,
   246  		},
   247  
   248  		// A non-default version, atm this should result in a failure.
   249  		{
   250  			version: 99,
   251  			valid:   false,
   252  		},
   253  	}
   254  	for i, versionCase := range versionTestCases {
   255  		// First, we'll re-assign SCB version to what was indicated in
   256  		// the test case.
   257  		singleChanBackup.Version = versionCase.version
   258  
   259  		var b bytes.Buffer
   260  
   261  		err := singleChanBackup.PackToWriter(&b, keyRing)
   262  		switch {
   263  		// If this is a valid test case, and we failed, then we'll
   264  		// return an error.
   265  		case err != nil && versionCase.valid:
   266  			t.Fatalf("#%v, unable to pack single: %v", i, err)
   267  
   268  		// If this is an invalid test case, and we passed it, then
   269  		// we'll return an error.
   270  		case err == nil && !versionCase.valid:
   271  			t.Fatalf("#%v got nil error for invalid pack: %v",
   272  				i, err)
   273  		}
   274  
   275  		// If this is a valid test case, then we'll continue to ensure
   276  		// we can unpack it, and also that if we mutate the packed
   277  		// version, then we trigger an error.
   278  		if versionCase.valid {
   279  			var unpackedSingle Single
   280  			err = unpackedSingle.UnpackFromReader(&b, keyRing)
   281  			if err != nil {
   282  				t.Fatalf("#%v unable to unpack single: %v",
   283  					i, err)
   284  			}
   285  
   286  			assertSingleEqual(t, singleChanBackup, unpackedSingle)
   287  
   288  			// If this was a valid packing attempt, then we'll test
   289  			// to ensure that if we mutate the version prepended to
   290  			// the serialization, then unpacking will fail as well.
   291  			var rawSingle bytes.Buffer
   292  			err := unpackedSingle.Serialize(&rawSingle)
   293  			if err != nil {
   294  				t.Fatalf("unable to serialize single: %v", err)
   295  			}
   296  
   297  			// Mutate the version byte to an unknown version.
   298  			rawBytes := rawSingle.Bytes()
   299  			rawBytes[0] = ^uint8(0)
   300  
   301  			newReader := bytes.NewReader(rawBytes)
   302  			err = unpackedSingle.Deserialize(newReader)
   303  			if err == nil {
   304  				t.Fatalf("#%v unpack with unknown version "+
   305  					"should have failed", i)
   306  			}
   307  		}
   308  	}
   309  }
   310  
   311  // TestPackedSinglesUnpack tests that we're able to properly unpack a series of
   312  // packed singles.
   313  func TestPackedSinglesUnpack(t *testing.T) {
   314  	t.Parallel()
   315  
   316  	keyRing := &mockKeyRing{}
   317  
   318  	// To start, we'll create 10 new singles, and them assemble their
   319  	// packed forms into a slice.
   320  	numSingles := 10
   321  	packedSingles := make([][]byte, 0, numSingles)
   322  	unpackedSingles := make([]Single, 0, numSingles)
   323  	for i := 0; i < numSingles; i++ {
   324  		channel, err := genRandomOpenChannelShell()
   325  		if err != nil {
   326  			t.Fatalf("unable to gen channel: %v", err)
   327  		}
   328  
   329  		single := NewSingle(channel, nil)
   330  
   331  		var b bytes.Buffer
   332  		if err := single.PackToWriter(&b, keyRing); err != nil {
   333  			t.Fatalf("unable to pack single: %v", err)
   334  		}
   335  
   336  		packedSingles = append(packedSingles, b.Bytes())
   337  		unpackedSingles = append(unpackedSingles, single)
   338  	}
   339  
   340  	// With all singles packed, we'll create the grouped type and attempt
   341  	// to Unpack all of them in a single go.
   342  	freshSingles, err := PackedSingles(packedSingles).Unpack(keyRing)
   343  	if err != nil {
   344  		t.Fatalf("unable to unpack singles: %v", err)
   345  	}
   346  
   347  	// The set of freshly unpacked singles should exactly match the initial
   348  	// set of singles that we packed before.
   349  	for i := 0; i < len(unpackedSingles); i++ {
   350  		assertSingleEqual(t, unpackedSingles[i], freshSingles[i])
   351  	}
   352  
   353  	// If we mutate one of the packed singles, then the entire method
   354  	// should fail.
   355  	packedSingles[0][0] ^= 1
   356  	_, err = PackedSingles(packedSingles).Unpack(keyRing)
   357  	if err == nil {
   358  		t.Fatalf("unpack attempt should fail")
   359  	}
   360  }
   361  
   362  // TestSinglePackStaticChanBackups tests that we're able to batch pack a set of
   363  // Singles, and then unpack them obtaining the same set of unpacked singles.
   364  func TestSinglePackStaticChanBackups(t *testing.T) {
   365  	t.Parallel()
   366  
   367  	keyRing := &mockKeyRing{}
   368  
   369  	// First, we'll create a set of random single, and along the way,
   370  	// create a map that will let us look up each single by its chan point.
   371  	numSingles := 10
   372  	singleMap := make(map[wire.OutPoint]Single, numSingles)
   373  	unpackedSingles := make([]Single, 0, numSingles)
   374  	for i := 0; i < numSingles; i++ {
   375  		channel, err := genRandomOpenChannelShell()
   376  		if err != nil {
   377  			t.Fatalf("unable to gen channel: %v", err)
   378  		}
   379  
   380  		single := NewSingle(channel, nil)
   381  
   382  		singleMap[channel.FundingOutpoint] = single
   383  		unpackedSingles = append(unpackedSingles, single)
   384  	}
   385  
   386  	// Now that we have all of our singles are created, we'll attempt to
   387  	// pack them all in a single batch.
   388  	packedSingleMap, err := PackStaticChanBackups(unpackedSingles, keyRing)
   389  	if err != nil {
   390  		t.Fatalf("unable to pack backups: %v", err)
   391  	}
   392  
   393  	// With our packed singles obtained, we'll ensure that each of them
   394  	// match their unpacked counterparts after they themselves have been
   395  	// unpacked.
   396  	for chanPoint, single := range singleMap {
   397  		packedSingles, ok := packedSingleMap[chanPoint]
   398  		if !ok {
   399  			t.Fatalf("unable to find single %v", chanPoint)
   400  		}
   401  
   402  		var freshSingle Single
   403  		err := freshSingle.UnpackFromReader(
   404  			bytes.NewReader(packedSingles), keyRing,
   405  		)
   406  		if err != nil {
   407  			t.Fatalf("unable to unpack single: %v", err)
   408  		}
   409  
   410  		assertSingleEqual(t, single, freshSingle)
   411  	}
   412  
   413  	// If we attempt to pack again, but force the key ring to fail, then
   414  	// the entire method should fail.
   415  	_, err = PackStaticChanBackups(
   416  		unpackedSingles, &mockKeyRing{true},
   417  	)
   418  	if err == nil {
   419  		t.Fatalf("pack attempt should fail")
   420  	}
   421  }
   422  
   423  // TestSingleUnconfirmedChannel tests that unconfirmed channels get serialized
   424  // correctly by encoding the funding broadcast height as block height of the
   425  // short channel ID.
   426  func TestSingleUnconfirmedChannel(t *testing.T) {
   427  	t.Parallel()
   428  
   429  	var fundingBroadcastHeight = uint32(1234)
   430  
   431  	// Let's create an open channel shell that contains all the information
   432  	// we need to create a static channel backup but simulate an
   433  	// unconfirmed channel by setting the block height to 0.
   434  	channel, err := genRandomOpenChannelShell()
   435  	if err != nil {
   436  		t.Fatalf("unable to gen open channel: %v", err)
   437  	}
   438  	channel.ShortChannelID.BlockHeight = 0
   439  	channel.FundingBroadcastHeight = fundingBroadcastHeight
   440  
   441  	singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2})
   442  	keyRing := &mockKeyRing{}
   443  
   444  	// Pack it and then unpack it again to make sure everything is written
   445  	// correctly, then check that the block height of the unpacked
   446  	// is the funding broadcast height we set before.
   447  	var b bytes.Buffer
   448  	if err := singleChanBackup.PackToWriter(&b, keyRing); err != nil {
   449  		t.Fatalf("unable to pack single: %v", err)
   450  	}
   451  	var unpackedSingle Single
   452  	err = unpackedSingle.UnpackFromReader(&b, keyRing)
   453  	if err != nil {
   454  		t.Fatalf("unable to unpack single: %v", err)
   455  	}
   456  	if unpackedSingle.ShortChannelID.BlockHeight != fundingBroadcastHeight {
   457  		t.Fatalf("invalid block height. got %d expected %d.",
   458  			unpackedSingle.ShortChannelID.BlockHeight,
   459  			fundingBroadcastHeight)
   460  	}
   461  }
   462  
   463  // TODO(roasbsef): fuzz parsing