github.com/lbryio/lbcd@v0.22.119/claimtrie/claimtrie_test.go (about)

     1  package claimtrie
     2  
     3  import (
     4  	"math/rand"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/lbryio/lbcd/claimtrie/change"
     9  	"github.com/lbryio/lbcd/claimtrie/config"
    10  	"github.com/lbryio/lbcd/claimtrie/merkletrie"
    11  	"github.com/lbryio/lbcd/claimtrie/param"
    12  
    13  	"github.com/lbryio/lbcd/chaincfg/chainhash"
    14  	"github.com/lbryio/lbcd/wire"
    15  
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  var cfg = config.DefaultConfig
    20  
    21  func setup(t *testing.T) {
    22  	param.SetNetwork(wire.TestNet)
    23  	cfg.DataDir = t.TempDir()
    24  }
    25  
    26  func b(s string) []byte {
    27  	return []byte(s)
    28  }
    29  
    30  func buildTx(hash chainhash.Hash) *wire.MsgTx {
    31  	tx := wire.NewMsgTx(1)
    32  	txIn := wire.NewTxIn(wire.NewOutPoint(&hash, 0), nil, nil)
    33  	tx.AddTxIn(txIn)
    34  	tx.AddTxOut(wire.NewTxOut(0, nil))
    35  	return tx
    36  }
    37  
    38  func TestFixedHashes(t *testing.T) {
    39  
    40  	r := require.New(t)
    41  
    42  	setup(t)
    43  	ct, err := New(cfg)
    44  	r.NoError(err)
    45  	defer ct.Close()
    46  
    47  	r.Equal(merkletrie.EmptyTrieHash[:], ct.MerkleHash()[:])
    48  
    49  	tx1 := buildTx(*merkletrie.EmptyTrieHash)
    50  	tx2 := buildTx(tx1.TxHash())
    51  	tx3 := buildTx(tx2.TxHash())
    52  	tx4 := buildTx(tx3.TxHash())
    53  
    54  	err = ct.AddClaim(b("test"), tx1.TxIn[0].PreviousOutPoint, change.NewClaimID(tx1.TxIn[0].PreviousOutPoint), 50)
    55  	r.NoError(err)
    56  
    57  	err = ct.AddClaim(b("test2"), tx2.TxIn[0].PreviousOutPoint, change.NewClaimID(tx2.TxIn[0].PreviousOutPoint), 50)
    58  	r.NoError(err)
    59  
    60  	err = ct.AddClaim(b("test"), tx3.TxIn[0].PreviousOutPoint, change.NewClaimID(tx3.TxIn[0].PreviousOutPoint), 50)
    61  	r.NoError(err)
    62  
    63  	err = ct.AddClaim(b("tes"), tx4.TxIn[0].PreviousOutPoint, change.NewClaimID(tx4.TxIn[0].PreviousOutPoint), 50)
    64  	r.NoError(err)
    65  
    66  	incrementBlock(r, ct, 1)
    67  
    68  	expected, err := chainhash.NewHashFromStr("938fb93364bf8184e0b649c799ae27274e8db5221f1723c99fb2acd3386cfb00")
    69  	r.NoError(err)
    70  	r.Equal(expected[:], ct.MerkleHash()[:])
    71  }
    72  
    73  func TestEmptyHashFork(t *testing.T) {
    74  	r := require.New(t)
    75  
    76  	setup(t)
    77  	param.ActiveParams.AllClaimsInMerkleForkHeight = 2
    78  	ct, err := New(cfg)
    79  	r.NoError(err)
    80  	r.NotNil(ct)
    81  	defer ct.Close()
    82  
    83  	for i := 0; i < 5; i++ {
    84  		err := ct.AppendBlock(false)
    85  		r.NoError(err)
    86  	}
    87  }
    88  
    89  func TestNormalizationFork(t *testing.T) {
    90  	r := require.New(t)
    91  
    92  	setup(t)
    93  	param.ActiveParams.NormalizedNameForkHeight = 2
    94  	ct, err := New(cfg)
    95  	r.NoError(err)
    96  	r.NotNil(ct)
    97  	defer ct.Close()
    98  
    99  	hash := chainhash.HashH([]byte{1, 2, 3})
   100  
   101  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   102  	err = ct.AddClaim([]byte("AÑEJO"), o1, change.NewClaimID(o1), 10)
   103  	r.NoError(err)
   104  
   105  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   106  	err = ct.AddClaim([]byte("AÑejo"), o2, change.NewClaimID(o2), 5)
   107  	r.NoError(err)
   108  
   109  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   110  	err = ct.AddClaim([]byte("あてはまる"), o3, change.NewClaimID(o3), 5)
   111  	r.NoError(err)
   112  
   113  	o4 := wire.OutPoint{Hash: hash, Index: 4}
   114  	err = ct.AddClaim([]byte("Aḿlie"), o4, change.NewClaimID(o4), 5)
   115  	r.NoError(err)
   116  
   117  	o5 := wire.OutPoint{Hash: hash, Index: 5}
   118  	err = ct.AddClaim([]byte("TEST"), o5, change.NewClaimID(o5), 5)
   119  	r.NoError(err)
   120  
   121  	o6 := wire.OutPoint{Hash: hash, Index: 6}
   122  	err = ct.AddClaim([]byte("test"), o6, change.NewClaimID(o6), 7)
   123  	r.NoError(err)
   124  
   125  	o7 := wire.OutPoint{Hash: hash, Index: 7}
   126  	err = ct.AddSupport([]byte("test"), o7, 11, change.NewClaimID(o6))
   127  	r.NoError(err)
   128  
   129  	incrementBlock(r, ct, 1)
   130  	r.NotEqual(merkletrie.EmptyTrieHash[:], ct.MerkleHash()[:])
   131  
   132  	n, err := ct.nodeManager.NodeAt(ct.nodeManager.Height(), []byte("AÑEJO"))
   133  	r.NoError(err)
   134  	r.NotNil(n.BestClaim)
   135  	r.Equal(int32(1), n.TakenOverAt)
   136  
   137  	o8 := wire.OutPoint{Hash: hash, Index: 8}
   138  	err = ct.AddClaim([]byte("aÑEJO"), o8, change.NewClaimID(o8), 8)
   139  	r.NoError(err)
   140  
   141  	incrementBlock(r, ct, 1)
   142  	r.NotEqual(merkletrie.EmptyTrieHash[:], ct.MerkleHash()[:])
   143  
   144  	n, err = ct.nodeManager.NodeAt(ct.nodeManager.Height(), []byte("añejo"))
   145  	r.NoError(err)
   146  	r.Equal(3, len(n.Claims))
   147  	r.Equal(uint32(1), n.BestClaim.OutPoint.Index)
   148  	r.Equal(int32(2), n.TakenOverAt)
   149  
   150  	n, err = ct.nodeManager.NodeAt(ct.nodeManager.Height(), []byte("test"))
   151  	r.NoError(err)
   152  	r.Equal(int64(18), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
   153  }
   154  
   155  func TestActivationsOnNormalizationFork(t *testing.T) {
   156  
   157  	r := require.New(t)
   158  
   159  	setup(t)
   160  	param.ActiveParams.NormalizedNameForkHeight = 4
   161  	ct, err := New(cfg)
   162  	r.NoError(err)
   163  	r.NotNil(ct)
   164  	defer ct.Close()
   165  
   166  	hash := chainhash.HashH([]byte{1, 2, 3})
   167  
   168  	o7 := wire.OutPoint{Hash: hash, Index: 7}
   169  	err = ct.AddClaim([]byte("A"), o7, change.NewClaimID(o7), 1)
   170  	r.NoError(err)
   171  	incrementBlock(r, ct, 3)
   172  	verifyBestIndex(t, ct, "A", 7, 1)
   173  
   174  	o8 := wire.OutPoint{Hash: hash, Index: 8}
   175  	err = ct.AddClaim([]byte("A"), o8, change.NewClaimID(o8), 2)
   176  	r.NoError(err)
   177  	incrementBlock(r, ct, 1)
   178  	verifyBestIndex(t, ct, "a", 8, 2)
   179  
   180  	incrementBlock(r, ct, 2)
   181  	verifyBestIndex(t, ct, "a", 8, 2)
   182  
   183  	err = ct.ResetHeight(3)
   184  	r.NoError(err)
   185  	verifyBestIndex(t, ct, "A", 7, 1)
   186  }
   187  
   188  func TestNormalizationSortOrder(t *testing.T) {
   189  
   190  	r := require.New(t)
   191  	// this was an unfortunate bug; the normalization fork should not have activated anything
   192  	// alas, it's now part of our history; we hereby test it to keep it that way
   193  	setup(t)
   194  	param.ActiveParams.NormalizedNameForkHeight = 2
   195  	ct, err := New(cfg)
   196  	r.NoError(err)
   197  	r.NotNil(ct)
   198  	defer ct.Close()
   199  
   200  	hash := chainhash.HashH([]byte{1, 2, 3})
   201  
   202  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   203  	err = ct.AddClaim([]byte("A"), o1, change.NewClaimID(o1), 1)
   204  	r.NoError(err)
   205  
   206  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   207  	err = ct.AddClaim([]byte("A"), o2, change.NewClaimID(o2), 2)
   208  	r.NoError(err)
   209  
   210  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   211  	err = ct.AddClaim([]byte("a"), o3, change.NewClaimID(o3), 3)
   212  	r.NoError(err)
   213  
   214  	incrementBlock(r, ct, 1)
   215  	verifyBestIndex(t, ct, "A", 2, 2)
   216  	verifyBestIndex(t, ct, "a", 3, 1)
   217  
   218  	incrementBlock(r, ct, 1)
   219  	verifyBestIndex(t, ct, "a", 3, 3)
   220  }
   221  
   222  func verifyBestIndex(t *testing.T, ct *ClaimTrie, name string, idx uint32, claims int) {
   223  
   224  	r := require.New(t)
   225  
   226  	n, err := ct.nodeManager.NodeAt(ct.nodeManager.Height(), []byte(name))
   227  	r.NoError(err)
   228  	r.Equal(claims, len(n.Claims))
   229  	if claims > 0 {
   230  		r.Equal(idx, n.BestClaim.OutPoint.Index)
   231  	}
   232  }
   233  
   234  func TestRebuild(t *testing.T) {
   235  	r := require.New(t)
   236  	setup(t)
   237  	ct, err := New(cfg)
   238  	r.NoError(err)
   239  	r.NotNil(ct)
   240  	defer ct.Close()
   241  
   242  	hash := chainhash.HashH([]byte{1, 2, 3})
   243  
   244  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   245  	err = ct.AddClaim([]byte("test1"), o1, change.NewClaimID(o1), 1)
   246  	r.NoError(err)
   247  
   248  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   249  	err = ct.AddClaim([]byte("test2"), o2, change.NewClaimID(o2), 2)
   250  	r.NoError(err)
   251  
   252  	incrementBlock(r, ct, 1)
   253  
   254  	m := ct.MerkleHash()
   255  	r.NotNil(m)
   256  	r.NotEqual(*merkletrie.EmptyTrieHash, *m)
   257  
   258  	ct.merkleTrie = merkletrie.NewRamTrie()
   259  	ct.runFullTrieRebuild(nil, nil)
   260  
   261  	m2 := ct.MerkleHash()
   262  	r.NotNil(m2)
   263  	r.Equal(*m, *m2)
   264  }
   265  
   266  func BenchmarkClaimTrie_AppendBlock256(b *testing.B) {
   267  
   268  	addUpdateRemoveRandoms(b, 256)
   269  }
   270  
   271  func BenchmarkClaimTrie_AppendBlock4(b *testing.B) {
   272  
   273  	addUpdateRemoveRandoms(b, 4)
   274  }
   275  
   276  func addUpdateRemoveRandoms(b *testing.B, inBlock int) {
   277  	rand.Seed(42)
   278  	names := make([][]byte, 0, b.N)
   279  
   280  	for i := 0; i < b.N; i++ {
   281  		names = append(names, randomName())
   282  	}
   283  
   284  	var hashes []*chainhash.Hash
   285  
   286  	param.SetNetwork(wire.TestNet)
   287  	param.ActiveParams.OriginalClaimExpirationTime = 1000000
   288  	param.ActiveParams.ExtendedClaimExpirationTime = 1000000
   289  	cfg.DataDir = b.TempDir()
   290  
   291  	r := require.New(b)
   292  	ct, err := New(cfg)
   293  	r.NoError(err)
   294  	defer ct.Close()
   295  	h1 := chainhash.Hash{100, 200}
   296  
   297  	start := time.Now()
   298  	b.ResetTimer()
   299  
   300  	c := 0
   301  	for i := 0; i < b.N; i++ {
   302  		op := wire.OutPoint{Hash: h1, Index: uint32(i)}
   303  		id := change.NewClaimID(op)
   304  		err = ct.AddClaim(names[i], op, id, 500)
   305  		r.NoError(err)
   306  		if c++; c%inBlock == inBlock-1 {
   307  			incrementBlock(r, ct, 1)
   308  			hashes = append(hashes, ct.MerkleHash())
   309  		}
   310  	}
   311  
   312  	for i := 0; i < b.N; i++ {
   313  		op := wire.OutPoint{Hash: h1, Index: uint32(i)}
   314  		id := change.NewClaimID(op)
   315  		op.Hash[0] = 1
   316  		err = ct.UpdateClaim(names[i], op, 400, id)
   317  		r.NoError(err)
   318  		if c++; c%inBlock == inBlock-1 {
   319  			incrementBlock(r, ct, 1)
   320  			hashes = append(hashes, ct.MerkleHash())
   321  		}
   322  	}
   323  
   324  	for i := 0; i < b.N; i++ {
   325  		op := wire.OutPoint{Hash: h1, Index: uint32(i)}
   326  		id := change.NewClaimID(op)
   327  		op.Hash[0] = 2
   328  		err = ct.UpdateClaim(names[i], op, 300, id)
   329  		r.NoError(err)
   330  		if c++; c%inBlock == inBlock-1 {
   331  			incrementBlock(r, ct, 1)
   332  			hashes = append(hashes, ct.MerkleHash())
   333  		}
   334  	}
   335  
   336  	for i := 0; i < b.N; i++ {
   337  		op := wire.OutPoint{Hash: h1, Index: uint32(i)}
   338  		id := change.NewClaimID(op)
   339  		op.Hash[0] = 3
   340  		err = ct.SpendClaim(names[i], op, id)
   341  		r.NoError(err)
   342  		if c++; c%inBlock == inBlock-1 {
   343  			incrementBlock(r, ct, 1)
   344  			hashes = append(hashes, ct.MerkleHash())
   345  		}
   346  	}
   347  	incrementBlock(r, ct, 1)
   348  	hashes = append(hashes, ct.MerkleHash())
   349  
   350  	b.StopTimer()
   351  	ht := ct.height
   352  	h1 = *ct.MerkleHash()
   353  	b.Logf("Running AppendBlock bench with %d names in %f sec. Height: %d, Hash: %s",
   354  		b.N, time.Since(start).Seconds(), ht, h1.String())
   355  
   356  	// a very important test of the functionality:
   357  	for ct.height > 0 {
   358  		r.True(hashes[ct.height-1].IsEqual(ct.MerkleHash()))
   359  		err = ct.ResetHeight(ct.height - 1)
   360  		r.NoError(err)
   361  	}
   362  }
   363  
   364  func randomName() []byte {
   365  	name := make([]byte, rand.Intn(30)+10)
   366  	rand.Read(name)
   367  	for i := range name {
   368  		name[i] %= 56
   369  		name[i] += 65
   370  	}
   371  	return name
   372  }
   373  
   374  func incrementBlock(r *require.Assertions, ct *ClaimTrie, c int32) {
   375  	h := ct.height + c
   376  	if c < 0 {
   377  		err := ct.ResetHeight(ct.height + c)
   378  		r.NoError(err)
   379  	} else {
   380  		for ; c > 0; c-- {
   381  			err := ct.AppendBlock(false)
   382  			r.NoError(err)
   383  		}
   384  	}
   385  	r.Equal(h, ct.height)
   386  }
   387  
   388  func TestNormalizationRollback(t *testing.T) {
   389  	param.SetNetwork(wire.TestNet)
   390  	param.ActiveParams.OriginalClaimExpirationTime = 1000000
   391  	param.ActiveParams.ExtendedClaimExpirationTime = 1000000
   392  	cfg.DataDir = t.TempDir()
   393  
   394  	r := require.New(t)
   395  	ct, err := New(cfg)
   396  	r.NoError(err)
   397  	defer ct.Close()
   398  
   399  	r.Equal(int32(250), param.ActiveParams.NormalizedNameForkHeight)
   400  	incrementBlock(r, ct, 247)
   401  
   402  	h1 := chainhash.Hash{100, 200}
   403  	op := wire.OutPoint{Hash: h1, Index: 1}
   404  	id := change.NewClaimID(op)
   405  	err = ct.AddClaim([]byte("TEST"), op, id, 1000)
   406  	r.NoError(err)
   407  
   408  	incrementBlock(r, ct, 5)
   409  	incrementBlock(r, ct, -4)
   410  	err = ct.SpendClaim([]byte("TEST"), op, id)
   411  	r.NoError(err)
   412  	incrementBlock(r, ct, 1)
   413  	h := ct.MerkleHash()
   414  	r.True(h.IsEqual(merkletrie.EmptyTrieHash))
   415  	incrementBlock(r, ct, 3)
   416  	h2 := ct.MerkleHash()
   417  	r.True(h.IsEqual(h2))
   418  }
   419  
   420  func TestNormalizationRollbackFuzz(t *testing.T) {
   421  	rand.Seed(42)
   422  	var hashes []*chainhash.Hash
   423  
   424  	param.SetNetwork(wire.TestNet)
   425  	param.ActiveParams.OriginalClaimExpirationTime = 1000000
   426  	param.ActiveParams.ExtendedClaimExpirationTime = 1000000
   427  	cfg.DataDir = t.TempDir()
   428  
   429  	r := require.New(t)
   430  	ct, err := New(cfg)
   431  	r.NoError(err)
   432  	defer ct.Close()
   433  	h1 := chainhash.Hash{100, 200}
   434  
   435  	r.Equal(int32(250), param.ActiveParams.NormalizedNameForkHeight)
   436  	incrementBlock(r, ct, 240)
   437  
   438  	for j := 0; j < 10; j++ {
   439  		c := 0
   440  		for i := 0; i < 200; i++ {
   441  			op := wire.OutPoint{Hash: h1, Index: uint32(i)}
   442  			id := change.NewClaimID(op)
   443  			err = ct.AddClaim(randomName(), op, id, 500)
   444  			r.NoError(err)
   445  			if c++; c%10 == 9 {
   446  				incrementBlock(r, ct, 1)
   447  				hashes = append(hashes, ct.MerkleHash())
   448  			}
   449  		}
   450  		if j > 7 {
   451  			ct.runFullTrieRebuild(nil, nil)
   452  			h := ct.MerkleHash()
   453  			r.True(h.IsEqual(hashes[len(hashes)-1]))
   454  		}
   455  		for ct.height > 240 {
   456  			r.True(hashes[ct.height-1-240].IsEqual(ct.MerkleHash()))
   457  			err = ct.ResetHeight(ct.height - 1)
   458  			r.NoError(err)
   459  		}
   460  		hashes = hashes[:0]
   461  	}
   462  }
   463  
   464  func TestClaimReplace(t *testing.T) {
   465  	r := require.New(t)
   466  	setup(t)
   467  	ct, err := New(cfg)
   468  	r.NoError(err)
   469  	r.NotNil(ct)
   470  	defer ct.Close()
   471  
   472  	hash := chainhash.HashH([]byte{1, 2, 3})
   473  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   474  	err = ct.AddClaim([]byte("bass"), o1, change.NewClaimID(o1), 8)
   475  	r.NoError(err)
   476  
   477  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   478  	err = ct.AddClaim([]byte("basso"), o2, change.NewClaimID(o2), 10)
   479  	r.NoError(err)
   480  
   481  	incrementBlock(r, ct, 1)
   482  	n, err := ct.NodeAt(ct.height, []byte("bass"))
   483  	r.Equal(o1.String(), n.BestClaim.OutPoint.String())
   484  
   485  	err = ct.SpendClaim([]byte("bass"), o1, n.BestClaim.ClaimID)
   486  	r.NoError(err)
   487  
   488  	o4 := wire.OutPoint{Hash: hash, Index: 4}
   489  	err = ct.AddClaim([]byte("bassfisher"), o4, change.NewClaimID(o4), 12)
   490  	r.NoError(err)
   491  
   492  	incrementBlock(r, ct, 1)
   493  	n, err = ct.NodeAt(ct.height, []byte("bass"))
   494  	r.NoError(err)
   495  	r.True(n == nil || !n.HasActiveBestClaim())
   496  	n, err = ct.NodeAt(ct.height, []byte("bassfisher"))
   497  	r.Equal(o4.String(), n.BestClaim.OutPoint.String())
   498  }
   499  
   500  func TestGeneralClaim(t *testing.T) {
   501  	r := require.New(t)
   502  	setup(t)
   503  	ct, err := New(cfg)
   504  	r.NoError(err)
   505  	r.NotNil(ct)
   506  	defer ct.Close()
   507  
   508  	incrementBlock(r, ct, 1)
   509  
   510  	hash := chainhash.HashH([]byte{1, 2, 3})
   511  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   512  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 8)
   513  	r.NoError(err)
   514  
   515  	incrementBlock(r, ct, 1)
   516  	err = ct.ResetHeight(ct.height - 1)
   517  	r.NoError(err)
   518  	n, err := ct.NodeAt(ct.height, []byte("test"))
   519  	r.NoError(err)
   520  	r.True(n == nil || !n.HasActiveBestClaim())
   521  
   522  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 8)
   523  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   524  	err = ct.AddClaim([]byte("test"), o2, change.NewClaimID(o2), 8)
   525  	r.NoError(err)
   526  
   527  	incrementBlock(r, ct, 1)
   528  	incrementBlock(r, ct, -1)
   529  	n, err = ct.NodeAt(ct.height, []byte("test"))
   530  	r.NoError(err)
   531  	r.True(n == nil || !n.HasActiveBestClaim())
   532  
   533  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 8)
   534  	r.NoError(err)
   535  	incrementBlock(r, ct, 1)
   536  	err = ct.AddClaim([]byte("test"), o2, change.NewClaimID(o2), 8)
   537  	r.NoError(err)
   538  	incrementBlock(r, ct, 1)
   539  
   540  	incrementBlock(r, ct, -2)
   541  	n, err = ct.NodeAt(ct.height, []byte("test"))
   542  	r.NoError(err)
   543  	r.True(n == nil || !n.HasActiveBestClaim())
   544  }
   545  
   546  func TestClaimTakeover(t *testing.T) {
   547  	r := require.New(t)
   548  	setup(t)
   549  	param.ActiveParams.ActiveDelayFactor = 1
   550  
   551  	ct, err := New(cfg)
   552  	r.NoError(err)
   553  	r.NotNil(ct)
   554  	defer ct.Close()
   555  
   556  	incrementBlock(r, ct, 1)
   557  
   558  	hash := chainhash.HashH([]byte{1, 2, 3})
   559  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   560  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 8)
   561  	r.NoError(err)
   562  
   563  	incrementBlock(r, ct, 10)
   564  
   565  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   566  	err = ct.AddClaim([]byte("test"), o2, change.NewClaimID(o2), 18)
   567  	r.NoError(err)
   568  
   569  	incrementBlock(r, ct, 10)
   570  
   571  	n, err := ct.NodeAt(ct.height, []byte("test"))
   572  	r.NoError(err)
   573  	r.Equal(o1.String(), n.BestClaim.OutPoint.String())
   574  
   575  	incrementBlock(r, ct, 1)
   576  
   577  	n, err = ct.NodeAt(ct.height, []byte("test"))
   578  	r.NoError(err)
   579  	r.Equal(o2.String(), n.BestClaim.OutPoint.String())
   580  
   581  	incrementBlock(r, ct, -1)
   582  	n, err = ct.NodeAt(ct.height, []byte("test"))
   583  	r.NoError(err)
   584  	r.Equal(o1.String(), n.BestClaim.OutPoint.String())
   585  }
   586  
   587  func TestSpendClaim(t *testing.T) {
   588  	r := require.New(t)
   589  	setup(t)
   590  	param.ActiveParams.ActiveDelayFactor = 1
   591  
   592  	ct, err := New(cfg)
   593  	r.NoError(err)
   594  	r.NotNil(ct)
   595  	defer ct.Close()
   596  
   597  	incrementBlock(r, ct, 1)
   598  
   599  	hash := chainhash.HashH([]byte{1, 2, 3})
   600  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   601  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 18)
   602  	r.NoError(err)
   603  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   604  	err = ct.AddClaim([]byte("test"), o2, change.NewClaimID(o2), 8)
   605  	r.NoError(err)
   606  
   607  	incrementBlock(r, ct, 1)
   608  
   609  	err = ct.SpendClaim([]byte("test"), o1, change.NewClaimID(o1))
   610  	r.NoError(err)
   611  
   612  	incrementBlock(r, ct, 1)
   613  
   614  	n, err := ct.NodeAt(ct.height, []byte("test"))
   615  	r.NoError(err)
   616  	r.Equal(o2.String(), n.BestClaim.OutPoint.String())
   617  
   618  	incrementBlock(r, ct, -1)
   619  
   620  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   621  	err = ct.AddClaim([]byte("test"), o3, change.NewClaimID(o3), 22)
   622  	r.NoError(err)
   623  
   624  	incrementBlock(r, ct, 10)
   625  
   626  	o4 := wire.OutPoint{Hash: hash, Index: 4}
   627  	err = ct.AddClaim([]byte("test"), o4, change.NewClaimID(o4), 28)
   628  	r.NoError(err)
   629  
   630  	incrementBlock(r, ct, 1)
   631  
   632  	n, err = ct.NodeAt(ct.height, []byte("test"))
   633  	r.NoError(err)
   634  	r.Equal(o3.String(), n.BestClaim.OutPoint.String())
   635  
   636  	err = ct.SpendClaim([]byte("test"), o3, n.BestClaim.ClaimID)
   637  	r.NoError(err)
   638  
   639  	incrementBlock(r, ct, 1)
   640  
   641  	n, err = ct.NodeAt(ct.height, []byte("test"))
   642  	r.NoError(err)
   643  	r.Equal(o4.String(), n.BestClaim.OutPoint.String())
   644  
   645  	err = ct.SpendClaim([]byte("test"), o1, change.NewClaimID(o1))
   646  	r.NoError(err)
   647  	err = ct.SpendClaim([]byte("test"), o2, change.NewClaimID(o2))
   648  	r.NoError(err)
   649  	err = ct.SpendClaim([]byte("test"), o3, change.NewClaimID(o3))
   650  	r.NoError(err)
   651  	err = ct.SpendClaim([]byte("test"), o4, change.NewClaimID(o4))
   652  	r.NoError(err)
   653  
   654  	incrementBlock(r, ct, 1)
   655  
   656  	n, err = ct.NodeAt(ct.height, []byte("test"))
   657  	r.NoError(err)
   658  	r.True(n == nil || !n.HasActiveBestClaim())
   659  
   660  	h := ct.MerkleHash()
   661  	r.Equal(merkletrie.EmptyTrieHash.String(), h.String())
   662  }
   663  
   664  func TestSupportDelay(t *testing.T) {
   665  	r := require.New(t)
   666  	setup(t)
   667  	param.ActiveParams.ActiveDelayFactor = 1
   668  
   669  	ct, err := New(cfg)
   670  	r.NoError(err)
   671  	r.NotNil(ct)
   672  	defer ct.Close()
   673  
   674  	incrementBlock(r, ct, 1)
   675  
   676  	hash := chainhash.HashH([]byte{1, 2, 3})
   677  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   678  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 18)
   679  	r.NoError(err)
   680  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   681  	err = ct.AddClaim([]byte("test"), o2, change.NewClaimID(o2), 8)
   682  	r.NoError(err)
   683  
   684  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   685  	err = ct.AddSupport([]byte("test"), o3, 18, change.NewClaimID(o3)) // using bad ClaimID on purpose
   686  	r.NoError(err)
   687  	o4 := wire.OutPoint{Hash: hash, Index: 4}
   688  	err = ct.AddSupport([]byte("test"), o4, 18, change.NewClaimID(o2))
   689  	r.NoError(err)
   690  
   691  	incrementBlock(r, ct, 1)
   692  
   693  	n, err := ct.NodeAt(ct.height, []byte("test"))
   694  	r.NoError(err)
   695  	r.Equal(o2.String(), n.BestClaim.OutPoint.String())
   696  
   697  	incrementBlock(r, ct, 10)
   698  
   699  	o5 := wire.OutPoint{Hash: hash, Index: 5}
   700  	err = ct.AddSupport([]byte("test"), o5, 18, change.NewClaimID(o1))
   701  	r.NoError(err)
   702  
   703  	incrementBlock(r, ct, 1)
   704  
   705  	n, err = ct.NodeAt(ct.height, []byte("test"))
   706  	r.NoError(err)
   707  	r.Equal(o2.String(), n.BestClaim.OutPoint.String())
   708  
   709  	incrementBlock(r, ct, 11)
   710  
   711  	n, err = ct.NodeAt(ct.height, []byte("test"))
   712  	r.NoError(err)
   713  	r.Equal(o1.String(), n.BestClaim.OutPoint.String())
   714  
   715  	incrementBlock(r, ct, -1)
   716  
   717  	n, err = ct.NodeAt(ct.height, []byte("test"))
   718  	r.NoError(err)
   719  	r.Equal(o2.String(), n.BestClaim.OutPoint.String())
   720  }
   721  
   722  func TestSupportSpending(t *testing.T) {
   723  	r := require.New(t)
   724  	setup(t)
   725  	param.ActiveParams.ActiveDelayFactor = 1
   726  
   727  	ct, err := New(cfg)
   728  	r.NoError(err)
   729  	r.NotNil(ct)
   730  	defer ct.Close()
   731  
   732  	incrementBlock(r, ct, 1)
   733  
   734  	hash := chainhash.HashH([]byte{1, 2, 3})
   735  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   736  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 18)
   737  	r.NoError(err)
   738  
   739  	incrementBlock(r, ct, 1)
   740  
   741  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   742  	err = ct.AddSupport([]byte("test"), o3, 18, change.NewClaimID(o1))
   743  	r.NoError(err)
   744  
   745  	err = ct.SpendClaim([]byte("test"), o1, change.NewClaimID(o1))
   746  	r.NoError(err)
   747  
   748  	incrementBlock(r, ct, 1)
   749  
   750  	n, err := ct.NodeAt(ct.height, []byte("test"))
   751  	r.NoError(err)
   752  	r.True(n == nil || !n.HasActiveBestClaim())
   753  }
   754  
   755  func TestSupportOnUpdate(t *testing.T) {
   756  	r := require.New(t)
   757  	setup(t)
   758  	param.ActiveParams.ActiveDelayFactor = 1
   759  
   760  	ct, err := New(cfg)
   761  	r.NoError(err)
   762  	r.NotNil(ct)
   763  	defer ct.Close()
   764  
   765  	incrementBlock(r, ct, 1)
   766  
   767  	hash := chainhash.HashH([]byte{1, 2, 3})
   768  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   769  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 18)
   770  	r.NoError(err)
   771  
   772  	err = ct.SpendClaim([]byte("test"), o1, change.NewClaimID(o1))
   773  	r.NoError(err)
   774  
   775  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   776  	err = ct.UpdateClaim([]byte("test"), o2, 28, change.NewClaimID(o1))
   777  	r.NoError(err)
   778  
   779  	incrementBlock(r, ct, 1)
   780  
   781  	n, err := ct.NodeAt(ct.height, []byte("test"))
   782  	r.NoError(err)
   783  	r.Equal(int64(28), n.BestClaim.Amount)
   784  
   785  	incrementBlock(r, ct, 1)
   786  
   787  	err = ct.SpendClaim([]byte("test"), o2, change.NewClaimID(o1))
   788  	r.NoError(err)
   789  
   790  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   791  	err = ct.UpdateClaim([]byte("test"), o3, 38, change.NewClaimID(o1))
   792  	r.NoError(err)
   793  
   794  	o4 := wire.OutPoint{Hash: hash, Index: 4}
   795  	err = ct.AddSupport([]byte("test"), o4, 2, change.NewClaimID(o1))
   796  	r.NoError(err)
   797  
   798  	o5 := wire.OutPoint{Hash: hash, Index: 5}
   799  	err = ct.AddClaim([]byte("test"), o5, change.NewClaimID(o5), 39)
   800  	r.NoError(err)
   801  
   802  	incrementBlock(r, ct, 1)
   803  
   804  	n, err = ct.NodeAt(ct.height, []byte("test"))
   805  	r.NoError(err)
   806  	r.Equal(int64(40), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
   807  
   808  	err = ct.SpendSupport([]byte("test"), o4, n.BestClaim.ClaimID)
   809  	r.NoError(err)
   810  
   811  	incrementBlock(r, ct, 1)
   812  
   813  	// NOTE: LBRYcrd did not test that supports can trigger a takeover correctly (and it doesn't work here):
   814  	// n, err = ct.NodeAt(ct.height, []byte("test"))
   815  	// r.NoError(err)
   816  	// r.Equal(int64(39), n.BestClaim.Amount + n.SupportSums[n.BestClaim.ClaimID.Key()])
   817  }
   818  
   819  func TestSupportPreservation(t *testing.T) {
   820  	r := require.New(t)
   821  	setup(t)
   822  	param.ActiveParams.ActiveDelayFactor = 1
   823  
   824  	ct, err := New(cfg)
   825  	r.NoError(err)
   826  	r.NotNil(ct)
   827  	defer ct.Close()
   828  
   829  	incrementBlock(r, ct, 1)
   830  
   831  	hash := chainhash.HashH([]byte{1, 2, 3})
   832  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   833  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   834  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   835  	o4 := wire.OutPoint{Hash: hash, Index: 4}
   836  	o5 := wire.OutPoint{Hash: hash, Index: 5}
   837  
   838  	err = ct.AddSupport([]byte("test"), o2, 10, change.NewClaimID(o1))
   839  	r.NoError(err)
   840  
   841  	incrementBlock(r, ct, 1)
   842  
   843  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 18)
   844  	r.NoError(err)
   845  
   846  	err = ct.AddClaim([]byte("test"), o3, change.NewClaimID(o3), 7)
   847  	r.NoError(err)
   848  
   849  	incrementBlock(r, ct, 10)
   850  
   851  	n, err := ct.NodeAt(ct.height, []byte("test"))
   852  	r.NoError(err)
   853  	r.Equal(int64(28), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
   854  
   855  	err = ct.AddSupport([]byte("test"), o4, 10, change.NewClaimID(o1))
   856  	r.NoError(err)
   857  	err = ct.AddSupport([]byte("test"), o5, 100, change.NewClaimID(o3))
   858  	r.NoError(err)
   859  
   860  	incrementBlock(r, ct, 1)
   861  
   862  	n, err = ct.NodeAt(ct.height, []byte("test"))
   863  	r.NoError(err)
   864  	r.Equal(int64(38), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
   865  
   866  	incrementBlock(r, ct, 10)
   867  
   868  	n, err = ct.NodeAt(ct.height, []byte("test"))
   869  	r.NoError(err)
   870  	r.Equal(int64(107), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
   871  }
   872  
   873  func TestInvalidClaimID(t *testing.T) {
   874  	r := require.New(t)
   875  	setup(t)
   876  	param.ActiveParams.ActiveDelayFactor = 1
   877  
   878  	ct, err := New(cfg)
   879  	r.NoError(err)
   880  	r.NotNil(ct)
   881  	defer ct.Close()
   882  
   883  	incrementBlock(r, ct, 1)
   884  
   885  	hash := chainhash.HashH([]byte{1, 2, 3})
   886  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   887  	o2 := wire.OutPoint{Hash: hash, Index: 2}
   888  	o3 := wire.OutPoint{Hash: hash, Index: 3}
   889  
   890  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 10)
   891  	r.NoError(err)
   892  
   893  	incrementBlock(r, ct, 1)
   894  
   895  	err = ct.SpendClaim([]byte("test"), o3, change.NewClaimID(o1))
   896  	r.NoError(err)
   897  
   898  	err = ct.UpdateClaim([]byte("test"), o2, 18, change.NewClaimID(o3))
   899  	r.NoError(err)
   900  
   901  	incrementBlock(r, ct, 12)
   902  
   903  	n, err := ct.NodeAt(ct.height, []byte("test"))
   904  	r.NoError(err)
   905  	r.Len(n.Claims, 1)
   906  	r.Len(n.Supports, 0)
   907  	r.Equal(int64(10), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
   908  }
   909  
   910  func TestStableTrieHash(t *testing.T) {
   911  	r := require.New(t)
   912  	setup(t)
   913  	param.ActiveParams.ActiveDelayFactor = 1
   914  	param.ActiveParams.AllClaimsInMerkleForkHeight = 8 // changes on this one
   915  
   916  	ct, err := New(cfg)
   917  	r.NoError(err)
   918  	r.NotNil(ct)
   919  	defer ct.Close()
   920  
   921  	hash := chainhash.HashH([]byte{1, 2, 3})
   922  	o1 := wire.OutPoint{Hash: hash, Index: 1}
   923  
   924  	err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 1)
   925  	r.NoError(err)
   926  
   927  	incrementBlock(r, ct, 1)
   928  
   929  	h := ct.MerkleHash()
   930  	r.NotEqual(merkletrie.EmptyTrieHash.String(), h.String())
   931  
   932  	for i := 0; i < 6; i++ {
   933  		incrementBlock(r, ct, 1)
   934  		r.Equal(h.String(), ct.MerkleHash().String())
   935  	}
   936  
   937  	incrementBlock(r, ct, 1)
   938  
   939  	r.NotEqual(h.String(), ct.MerkleHash())
   940  	h = ct.MerkleHash()
   941  
   942  	for i := 0; i < 16; i++ {
   943  		incrementBlock(r, ct, 1)
   944  		r.Equal(h.String(), ct.MerkleHash().String())
   945  	}
   946  }
   947  
   948  func TestBlock884431(t *testing.T) {
   949  	r := require.New(t)
   950  	setup(t)
   951  	param.ActiveParams.ActiveDelayFactor = 1
   952  	param.ActiveParams.MaxRemovalWorkaroundHeight = 0
   953  	param.ActiveParams.AllClaimsInMerkleForkHeight = 0
   954  
   955  	ct, err := New(cfg)
   956  	r.NoError(err)
   957  	r.NotNil(ct)
   958  	defer ct.Close()
   959  
   960  	// in this block we have a scenario where we update all the child names
   961  	// which, in the old code, caused a trie vertex to be removed
   962  	// which, in turn, would trigger a premature takeover
   963  
   964  	c := byte(10)
   965  
   966  	add := func(s string, amt int64) wire.OutPoint {
   967  		h := chainhash.HashH([]byte{c})
   968  		c++
   969  		o := wire.OutPoint{Hash: h, Index: 1}
   970  		err := ct.AddClaim([]byte(s), o, change.NewClaimID(o), amt)
   971  		r.NoError(err)
   972  		return o
   973  	}
   974  
   975  	update := func(s string, o wire.OutPoint, amt int64) wire.OutPoint {
   976  		err = ct.SpendClaim([]byte(s), o, change.NewClaimID(o))
   977  		r.NoError(err)
   978  
   979  		h := chainhash.HashH([]byte{c})
   980  		c++
   981  		o2 := wire.OutPoint{Hash: h, Index: 2}
   982  
   983  		err = ct.UpdateClaim([]byte(s), o2, amt, change.NewClaimID(o))
   984  		r.NoError(err)
   985  		return o2
   986  	}
   987  
   988  	o1a := add("go", 10)
   989  	o1b := add("go", 20)
   990  	o2 := add("goop", 10)
   991  	o3 := add("gog", 20)
   992  
   993  	o4a := add("test", 10)
   994  	o4b := add("test", 20)
   995  	o5 := add("tester", 10)
   996  	o6 := add("testing", 20)
   997  
   998  	for i := 0; i < 10; i++ {
   999  		err = ct.AppendBlock(false)
  1000  		r.NoError(err)
  1001  	}
  1002  	n, err := ct.NodeAt(ct.height, []byte("go"))
  1003  	r.NoError(err)
  1004  	r.Equal(o1b.String(), n.BestClaim.OutPoint.String())
  1005  	n, err = ct.NodeAt(ct.height, []byte("test"))
  1006  	r.NoError(err)
  1007  	r.Equal(o4b.String(), n.BestClaim.OutPoint.String())
  1008  
  1009  	update("go", o1b, 30)
  1010  	o10 := update("go", o1a, 40)
  1011  	update("gog", o3, 30)
  1012  	update("goop", o2, 30)
  1013  
  1014  	update("testing", o6, 30)
  1015  	o11 := update("test", o4b, 30)
  1016  	update("test", o4a, 40)
  1017  	update("tester", o5, 30)
  1018  
  1019  	incrementBlock(r, ct, 1)
  1020  
  1021  	n, err = ct.NodeAt(ct.height, []byte("go"))
  1022  	r.NoError(err)
  1023  	r.Equal(o10.String(), n.BestClaim.OutPoint.String())
  1024  	n, err = ct.NodeAt(ct.height, []byte("test"))
  1025  	r.NoError(err)
  1026  	r.Equal(o11.String(), n.BestClaim.OutPoint.String())
  1027  }