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 }