github.com/MetalBlockchain/metalgo@v1.11.9/snow/consensus/snowball/tree_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 //nolint:goconst 5 package snowball 6 7 import ( 8 "strings" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "gonum.org/v1/gonum/mathext/prng" 13 14 "github.com/MetalBlockchain/metalgo/ids" 15 "github.com/MetalBlockchain/metalgo/utils/bag" 16 ) 17 18 const initialUnaryDescription = "SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [0, 256)" 19 20 func TestSnowballSingleton(t *testing.T) { 21 require := require.New(t) 22 23 params := Parameters{ 24 K: 1, 25 AlphaPreference: 1, 26 AlphaConfidence: 1, 27 Beta: 2, 28 } 29 tree := NewTree(SnowballFactory, params, Red) 30 31 require.False(tree.Finalized()) 32 33 oneRed := bag.Of(Red) 34 require.True(tree.RecordPoll(oneRed)) 35 require.False(tree.Finalized()) 36 37 empty := bag.Bag[ids.ID]{} 38 require.False(tree.RecordPoll(empty)) 39 require.False(tree.Finalized()) 40 41 require.True(tree.RecordPoll(oneRed)) 42 require.False(tree.Finalized()) 43 44 require.True(tree.RecordPoll(oneRed)) 45 require.Equal(Red, tree.Preference()) 46 require.True(tree.Finalized()) 47 48 tree.Add(Blue) 49 50 require.True(tree.Finalized()) 51 52 // Because the tree is already finalized, RecordPoll can return either true 53 // or false. 54 oneBlue := bag.Of(Blue) 55 tree.RecordPoll(oneBlue) 56 require.Equal(Red, tree.Preference()) 57 require.True(tree.Finalized()) 58 } 59 60 func TestSnowballRecordUnsuccessfulPoll(t *testing.T) { 61 require := require.New(t) 62 63 params := Parameters{ 64 K: 1, 65 AlphaPreference: 1, 66 AlphaConfidence: 1, 67 Beta: 3, 68 } 69 tree := NewTree(SnowballFactory, params, Red) 70 71 require.False(tree.Finalized()) 72 73 oneRed := bag.Of(Red) 74 require.True(tree.RecordPoll(oneRed)) 75 76 tree.RecordUnsuccessfulPoll() 77 78 require.True(tree.RecordPoll(oneRed)) 79 require.False(tree.Finalized()) 80 81 require.True(tree.RecordPoll(oneRed)) 82 require.False(tree.Finalized()) 83 84 require.True(tree.RecordPoll(oneRed)) 85 require.Equal(Red, tree.Preference()) 86 require.True(tree.Finalized()) 87 } 88 89 func TestSnowballBinary(t *testing.T) { 90 require := require.New(t) 91 92 params := Parameters{ 93 K: 1, 94 AlphaPreference: 1, 95 AlphaConfidence: 1, 96 Beta: 2, 97 } 98 tree := NewTree(SnowballFactory, params, Red) 99 tree.Add(Blue) 100 101 require.Equal(Red, tree.Preference()) 102 require.False(tree.Finalized()) 103 104 oneBlue := bag.Of(Blue) 105 require.True(tree.RecordPoll(oneBlue)) 106 require.Equal(Blue, tree.Preference()) 107 require.False(tree.Finalized()) 108 109 oneRed := bag.Of(Red) 110 require.True(tree.RecordPoll(oneRed)) 111 require.Equal(Blue, tree.Preference()) 112 require.False(tree.Finalized()) 113 114 require.True(tree.RecordPoll(oneBlue)) 115 require.Equal(Blue, tree.Preference()) 116 require.False(tree.Finalized()) 117 118 require.True(tree.RecordPoll(oneBlue)) 119 require.Equal(Blue, tree.Preference()) 120 require.True(tree.Finalized()) 121 } 122 123 func TestSnowballLastBinary(t *testing.T) { 124 require := require.New(t) 125 126 zero := ids.Empty 127 one := ids.ID{ 128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 132 } 133 134 params := Parameters{ 135 K: 1, 136 AlphaPreference: 1, 137 AlphaConfidence: 1, 138 Beta: 2, 139 } 140 tree := NewTree(SnowballFactory, params, zero) 141 tree.Add(one) 142 143 // Should do nothing 144 tree.Add(one) 145 146 expected := `SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [0, 255) 147 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 255` 148 require.Equal(expected, tree.String()) 149 require.Equal(zero, tree.Preference()) 150 require.False(tree.Finalized()) 151 152 oneBag := bag.Of(one) 153 require.True(tree.RecordPoll(oneBag)) 154 require.Equal(one, tree.Preference()) 155 require.False(tree.Finalized()) 156 157 expected = `SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [0, 255) 158 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 255` 159 require.Equal(expected, tree.String()) 160 161 require.True(tree.RecordPoll(oneBag)) 162 require.Equal(one, tree.Preference()) 163 require.True(tree.Finalized()) 164 165 expected = "SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 2, SF(Confidence = [2], Finalized = true, SL(Preference = 1))) Bit = 255" 166 require.Equal(expected, tree.String()) 167 } 168 169 func TestSnowballFirstBinary(t *testing.T) { 170 require := require.New(t) 171 172 zero := ids.Empty 173 one := ids.ID{0x01} 174 175 params := Parameters{ 176 K: 1, 177 AlphaPreference: 1, 178 AlphaConfidence: 1, 179 Beta: 2, 180 } 181 tree := NewTree(SnowballFactory, params, zero) 182 tree.Add(one) 183 184 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 185 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 186 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 187 require.Equal(expected, tree.String()) 188 require.Equal(zero, tree.Preference()) 189 require.False(tree.Finalized()) 190 191 oneBag := bag.Of(one) 192 require.True(tree.RecordPoll(oneBag)) 193 require.Equal(one, tree.Preference()) 194 require.False(tree.Finalized()) 195 196 expected = `SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 0 197 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 198 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [1, 256)` 199 require.Equal(expected, tree.String()) 200 201 require.True(tree.RecordPoll(oneBag)) 202 require.Equal(one, tree.Preference()) 203 require.True(tree.Finalized()) 204 205 expected = `SB(PreferenceStrength = 2, SF(Confidence = [2], Finalized = true)) Bits = [1, 256)` 206 require.Equal(expected, tree.String()) 207 } 208 209 func TestSnowballAddDecidedFirstBit(t *testing.T) { 210 require := require.New(t) 211 212 zero := ids.Empty 213 c1000 := ids.ID{0x01} 214 c1100 := ids.ID{0x03} 215 c0110 := ids.ID{0x06} 216 217 params := Parameters{ 218 K: 1, 219 AlphaPreference: 1, 220 AlphaConfidence: 1, 221 Beta: 2, 222 } 223 tree := NewTree(SnowballFactory, params, zero) 224 tree.Add(c1000) 225 tree.Add(c1100) 226 227 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 228 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 229 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 1 230 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 231 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 232 require.Equal(expected, tree.String()) 233 require.Equal(zero, tree.Preference()) 234 require.False(tree.Finalized()) 235 236 oneBag := bag.Of(c1000) 237 require.True(tree.RecordPoll(oneBag)) 238 require.Equal(c1000, tree.Preference()) 239 require.False(tree.Finalized()) 240 241 expected = `SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 0 242 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 243 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 244 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 245 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 246 require.Equal(expected, tree.String()) 247 248 threeBag := bag.Of(c1100) 249 require.True(tree.RecordPoll(threeBag)) 250 require.Equal(c1000, tree.Preference()) 251 require.False(tree.Finalized()) 252 253 expected = `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 254 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 255 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256)` 256 require.Equal(expected, tree.String()) 257 258 // Adding six should have no effect because the first bit is already decided 259 tree.Add(c0110) 260 require.Equal(expected, tree.String()) 261 } 262 263 func TestSnowballAddPreviouslyRejected(t *testing.T) { 264 require := require.New(t) 265 266 zero := ids.ID{0b00000000} 267 one := ids.ID{0b00000001} 268 two := ids.ID{0b00000010} 269 270 params := Parameters{ 271 K: 1, 272 AlphaPreference: 1, 273 AlphaConfidence: 1, 274 Beta: 2, 275 } 276 tree := NewTree(SnowballFactory, params, zero) 277 tree.Add(two) 278 279 { 280 expected := `SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [0, 1) 281 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 1 282 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 283 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 284 require.Equal(expected, tree.String()) 285 require.Equal(zero, tree.Preference()) 286 require.False(tree.Finalized()) 287 } 288 289 zeroBag := bag.Of(zero) 290 require.True(tree.RecordPoll(zeroBag)) 291 292 { 293 expected := `SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [0, 1) 294 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 295 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 296 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 297 require.Equal(expected, tree.String()) 298 require.Equal(zero, tree.Preference()) 299 require.False(tree.Finalized()) 300 } 301 302 twoBag := bag.Of(two) 303 require.True(tree.RecordPoll(twoBag)) 304 305 { 306 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 307 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 308 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256)` 309 require.Equal(expected, tree.String()) 310 require.Equal(zero, tree.Preference()) 311 require.False(tree.Finalized()) 312 } 313 314 tree.Add(one) 315 316 { 317 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 318 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 319 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256)` 320 require.Equal(expected, tree.String()) 321 require.Equal(zero, tree.Preference()) 322 require.False(tree.Finalized()) 323 } 324 } 325 326 func TestSnowballNewUnary(t *testing.T) { 327 require := require.New(t) 328 329 zero := ids.ID{0b00000000} 330 one := ids.ID{0b00000001} 331 332 params := Parameters{ 333 K: 1, 334 AlphaPreference: 1, 335 AlphaConfidence: 1, 336 Beta: 3, 337 } 338 tree := NewTree(SnowballFactory, params, zero) 339 tree.Add(one) 340 341 { 342 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 343 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 344 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 345 require.Equal(expected, tree.String()) 346 require.Equal(zero, tree.Preference()) 347 require.False(tree.Finalized()) 348 } 349 350 oneBag := bag.Of(one) 351 require.True(tree.RecordPoll(oneBag)) 352 353 { 354 expected := `SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 0 355 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 356 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [1, 256)` 357 require.Equal(expected, tree.String()) 358 require.Equal(one, tree.Preference()) 359 require.False(tree.Finalized()) 360 } 361 362 require.True(tree.RecordPoll(oneBag)) 363 364 { 365 expected := `SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 2, SF(Confidence = [2], Finalized = false, SL(Preference = 1))) Bit = 0 366 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 367 SB(PreferenceStrength = 2, SF(Confidence = [2], Finalized = false)) Bits = [1, 256)` 368 require.Equal(expected, tree.String()) 369 require.Equal(one, tree.Preference()) 370 require.False(tree.Finalized()) 371 } 372 } 373 374 func TestSnowballTransitiveReset(t *testing.T) { 375 require := require.New(t) 376 377 zero := ids.ID{0b00000000} 378 two := ids.ID{0b00000010} 379 eight := ids.ID{0b00001000} 380 381 params := Parameters{ 382 K: 1, 383 AlphaPreference: 1, 384 AlphaConfidence: 1, 385 Beta: 2, 386 } 387 tree := NewTree(SnowballFactory, params, zero) 388 tree.Add(two) 389 tree.Add(eight) 390 391 { 392 expected := `SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [0, 1) 393 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 1 394 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 3) 395 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 3 396 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [4, 256) 397 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [4, 256) 398 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 399 require.Equal(expected, tree.String()) 400 require.Equal(zero, tree.Preference()) 401 require.False(tree.Finalized()) 402 } 403 404 zeroBag := bag.Of(zero) 405 require.True(tree.RecordPoll(zeroBag)) 406 407 { 408 expected := `SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [0, 1) 409 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 410 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 3) 411 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 3 412 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [4, 256) 413 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [4, 256) 414 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 415 require.Equal(expected, tree.String()) 416 require.Equal(zero, tree.Preference()) 417 require.False(tree.Finalized()) 418 } 419 420 emptyBag := bag.Bag[ids.ID]{} 421 require.False(tree.RecordPoll(emptyBag)) 422 423 { 424 expected := `SB(PreferenceStrength = 1, SF(Confidence = [0], Finalized = false)) Bits = [0, 1) 425 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 426 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 3) 427 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 3 428 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [4, 256) 429 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [4, 256) 430 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 431 require.Equal(expected, tree.String()) 432 require.Equal(zero, tree.Preference()) 433 require.False(tree.Finalized()) 434 } 435 436 require.True(tree.RecordPoll(zeroBag)) 437 438 { 439 expected := `SB(PreferenceStrength = 2, SF(Confidence = [1], Finalized = false)) Bits = [0, 1) 440 SB(Preference = 0, PreferenceStrength[0] = 2, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 441 SB(PreferenceStrength = 2, SF(Confidence = [1], Finalized = false)) Bits = [2, 3) 442 SB(Preference = 0, PreferenceStrength[0] = 2, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 3 443 SB(PreferenceStrength = 2, SF(Confidence = [1], Finalized = false)) Bits = [4, 256) 444 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [4, 256) 445 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 446 require.Equal(expected, tree.String()) 447 require.Equal(zero, tree.Preference()) 448 require.False(tree.Finalized()) 449 } 450 451 require.True(tree.RecordPoll(zeroBag)) 452 453 { 454 expected := "SB(PreferenceStrength = 3, SF(Confidence = [2], Finalized = true)) Bits = [4, 256)" 455 require.Equal(expected, tree.String()) 456 require.Equal(zero, tree.Preference()) 457 require.True(tree.Finalized()) 458 } 459 } 460 461 func TestSnowballTrinary(t *testing.T) { 462 require := require.New(t) 463 464 params := Parameters{ 465 K: 1, 466 AlphaPreference: 1, 467 AlphaConfidence: 1, 468 Beta: 2, 469 } 470 tree := NewTree(SnowballFactory, params, Green) 471 tree.Add(Red) 472 tree.Add(Blue) 473 474 // * 475 // / \ 476 // R * 477 // / \ 478 // G B 479 480 require.Equal(Green, tree.Preference()) 481 require.False(tree.Finalized()) 482 483 redBag := bag.Of(Red) 484 require.True(tree.RecordPoll(redBag)) 485 require.Equal(Red, tree.Preference()) 486 require.False(tree.Finalized()) 487 488 blueBag := bag.Of(Blue) 489 require.True(tree.RecordPoll(blueBag)) 490 require.Equal(Red, tree.Preference()) 491 require.False(tree.Finalized()) 492 493 // Here is a case where voting for a color makes a different color become 494 // the preferred color. This is intended behavior. 495 greenBag := bag.Of(Green) 496 require.True(tree.RecordPoll(greenBag)) 497 require.Equal(Blue, tree.Preference()) 498 require.False(tree.Finalized()) 499 500 // Red has already been rejected here, so this is not a successful poll. 501 require.False(tree.RecordPoll(redBag)) 502 require.Equal(Blue, tree.Preference()) 503 require.False(tree.Finalized()) 504 505 require.True(tree.RecordPoll(greenBag)) 506 require.Equal(Green, tree.Preference()) 507 require.False(tree.Finalized()) 508 } 509 510 func TestSnowballCloseTrinary(t *testing.T) { 511 require := require.New(t) 512 513 yellow := ids.ID{0x01} 514 cyan := ids.ID{0x02} 515 magenta := ids.ID{0x03} 516 517 params := Parameters{ 518 K: 1, 519 AlphaPreference: 1, 520 AlphaConfidence: 1, 521 Beta: 2, 522 } 523 tree := NewTree(SnowballFactory, params, yellow) 524 tree.Add(cyan) 525 tree.Add(magenta) 526 527 // * 528 // / \ 529 // C * 530 // / \ 531 // Y M 532 533 require.Equal(yellow, tree.Preference()) 534 require.False(tree.Finalized()) 535 536 yellowBag := bag.Of(yellow) 537 require.True(tree.RecordPoll(yellowBag)) 538 require.Equal(yellow, tree.Preference()) 539 require.False(tree.Finalized()) 540 541 magentaBag := bag.Of(magenta) 542 require.True(tree.RecordPoll(magentaBag)) 543 require.Equal(yellow, tree.Preference()) 544 require.False(tree.Finalized()) 545 546 // Cyan has already been rejected here, so these are not successful polls. 547 cyanBag := bag.Of(cyan) 548 require.False(tree.RecordPoll(cyanBag)) 549 require.Equal(yellow, tree.Preference()) 550 require.False(tree.Finalized()) 551 552 require.False(tree.RecordPoll(cyanBag)) 553 require.Equal(yellow, tree.Preference()) 554 require.False(tree.Finalized()) 555 } 556 557 func TestSnowballResetChild(t *testing.T) { 558 require := require.New(t) 559 560 c0000 := ids.ID{0x00} // 0000 561 c0100 := ids.ID{0x02} // 0100 562 c1000 := ids.ID{0x01} // 1000 563 564 params := Parameters{ 565 K: 1, 566 AlphaPreference: 1, 567 AlphaConfidence: 1, 568 Beta: 2, 569 } 570 tree := NewTree(SnowballFactory, params, c0000) 571 tree.Add(c0100) 572 tree.Add(c1000) 573 574 require.Equal(c0000, tree.Preference()) 575 require.False(tree.Finalized()) 576 577 c0000Bag := bag.Of(c0000) 578 require.True(tree.RecordPoll(c0000Bag)) 579 580 { 581 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 582 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 583 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 584 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 585 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 586 require.Equal(expected, tree.String()) 587 require.Equal(c0000, tree.Preference()) 588 require.False(tree.Finalized()) 589 } 590 591 emptyBag := bag.Bag[ids.ID]{} 592 require.False(tree.RecordPoll(emptyBag)) 593 594 { 595 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 596 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 597 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 598 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 599 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 600 require.Equal(expected, tree.String()) 601 require.Equal(c0000, tree.Preference()) 602 require.False(tree.Finalized()) 603 } 604 605 require.True(tree.RecordPoll(c0000Bag)) 606 607 { 608 expected := `SB(Preference = 0, PreferenceStrength[0] = 2, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 609 SB(Preference = 0, PreferenceStrength[0] = 2, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 610 SB(PreferenceStrength = 2, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 611 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 612 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 613 require.Equal(expected, tree.String()) 614 require.Equal(c0000, tree.Preference()) 615 require.False(tree.Finalized()) 616 } 617 } 618 619 func TestSnowballResetSibling(t *testing.T) { 620 require := require.New(t) 621 622 c0000 := ids.ID{0x00} // 0000 623 c0100 := ids.ID{0x02} // 0100 624 c1000 := ids.ID{0x01} // 1000 625 626 params := Parameters{ 627 K: 1, 628 AlphaPreference: 1, 629 AlphaConfidence: 1, 630 Beta: 2, 631 } 632 tree := NewTree(SnowballFactory, params, c0000) 633 tree.Add(c0100) 634 tree.Add(c1000) 635 636 require.Equal(c0000, tree.Preference()) 637 require.False(tree.Finalized()) 638 639 c0100Bag := bag.Of(c0100) 640 require.True(tree.RecordPoll(c0100Bag)) 641 642 { 643 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 644 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 645 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 646 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 647 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 648 require.Equal(expected, tree.String()) 649 require.Equal(c0100, tree.Preference()) 650 require.False(tree.Finalized()) 651 } 652 653 c1000Bag := bag.Of(c1000) 654 require.True(tree.RecordPoll(c1000Bag)) 655 656 { 657 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 0 658 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 659 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 660 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 661 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [1, 256)` 662 require.Equal(expected, tree.String()) 663 require.Equal(c0100, tree.Preference()) 664 require.False(tree.Finalized()) 665 } 666 667 require.True(tree.RecordPoll(c0100Bag)) 668 669 { 670 expected := `SB(Preference = 0, PreferenceStrength[0] = 2, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 671 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 2, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 672 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 673 SB(PreferenceStrength = 2, SF(Confidence = [1], Finalized = false)) Bits = [2, 256) 674 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [1, 256)` 675 require.Equal(expected, tree.String()) 676 require.Equal(c0100, tree.Preference()) 677 require.False(tree.Finalized()) 678 } 679 } 680 681 func TestSnowball5Colors(t *testing.T) { 682 require := require.New(t) 683 684 numColors := 5 685 params := Parameters{ 686 K: 5, 687 AlphaPreference: 5, 688 AlphaConfidence: 5, 689 Beta: 20, 690 } 691 692 colors := []ids.ID{} 693 for i := 0; i < numColors; i++ { 694 colors = append(colors, ids.Empty.Prefix(uint64(i))) 695 } 696 697 tree0 := NewTree(SnowballFactory, params, colors[4]) 698 699 tree0.Add(colors[0]) 700 tree0.Add(colors[1]) 701 tree0.Add(colors[2]) 702 tree0.Add(colors[3]) 703 704 tree1 := NewTree(SnowballFactory, params, colors[3]) 705 706 tree1.Add(colors[0]) 707 tree1.Add(colors[1]) 708 tree1.Add(colors[2]) 709 tree1.Add(colors[4]) 710 711 s1 := tree0.String() 712 s2 := tree1.String() 713 require.Equal(strings.Count(s1, " "), strings.Count(s2, " ")) 714 } 715 716 func TestSnowballFineGrained(t *testing.T) { 717 require := require.New(t) 718 719 c0000 := ids.ID{0x00} 720 c1000 := ids.ID{0x01} 721 c1100 := ids.ID{0x03} 722 c0010 := ids.ID{0x04} 723 724 params := Parameters{ 725 K: 1, 726 AlphaPreference: 1, 727 AlphaConfidence: 1, 728 Beta: 2, 729 } 730 tree := NewTree(SnowballFactory, params, c0000) 731 732 require.Equal(initialUnaryDescription, tree.String()) 733 require.Equal(c0000, tree.Preference()) 734 require.False(tree.Finalized()) 735 736 tree.Add(c1100) 737 738 { 739 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 740 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 741 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 742 require.Equal(expected, tree.String()) 743 require.Equal(c0000, tree.Preference()) 744 require.False(tree.Finalized()) 745 } 746 747 tree.Add(c1000) 748 749 { 750 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 751 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 752 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 1))) Bit = 1 753 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 754 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 755 require.Equal(expected, tree.String()) 756 require.Equal(c0000, tree.Preference()) 757 require.False(tree.Finalized()) 758 } 759 760 tree.Add(c0010) 761 762 { 763 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 764 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 2) 765 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 2 766 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 767 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 768 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 1))) Bit = 1 769 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 770 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 771 require.Equal(expected, tree.String()) 772 require.Equal(c0000, tree.Preference()) 773 require.False(tree.Finalized()) 774 } 775 776 c0000Bag := bag.Of(c0000) 777 require.True(tree.RecordPoll(c0000Bag)) 778 779 { 780 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 781 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [1, 2) 782 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 2 783 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [3, 256) 784 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 785 SB(Preference = 1, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 1))) Bit = 1 786 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 787 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256)` 788 require.Equal(expected, tree.String()) 789 require.Equal(c0000, tree.Preference()) 790 require.False(tree.Finalized()) 791 } 792 793 c0010Bag := bag.Of(c0010) 794 require.True(tree.RecordPoll(c0010Bag)) 795 796 { 797 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 2 798 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [3, 256) 799 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [3, 256)` 800 require.Equal(expected, tree.String()) 801 require.Equal(c0000, tree.Preference()) 802 require.False(tree.Finalized()) 803 } 804 805 require.True(tree.RecordPoll(c0010Bag)) 806 { 807 expected := "SB(PreferenceStrength = 2, SF(Confidence = [2], Finalized = true)) Bits = [3, 256)" 808 require.Equal(expected, tree.String()) 809 require.Equal(c0010, tree.Preference()) 810 require.True(tree.Finalized()) 811 } 812 } 813 814 func TestSnowballDoubleAdd(t *testing.T) { 815 require := require.New(t) 816 817 params := Parameters{ 818 K: 1, 819 AlphaPreference: 1, 820 AlphaConfidence: 1, 821 Beta: 3, 822 } 823 tree := NewTree(SnowballFactory, params, Red) 824 tree.Add(Red) 825 826 require.Equal(initialUnaryDescription, tree.String()) 827 require.Equal(Red, tree.Preference()) 828 require.False(tree.Finalized()) 829 } 830 831 func TestSnowballConsistent(t *testing.T) { 832 require := require.New(t) 833 834 var ( 835 numColors = 50 836 numNodes = 100 837 params = Parameters{ 838 K: 20, 839 AlphaPreference: 15, 840 AlphaConfidence: 15, 841 Beta: 20, 842 } 843 seed uint64 = 0 844 source = prng.NewMT19937() 845 ) 846 847 n := NewNetwork(SnowballFactory, params, numColors, source) 848 849 source.Seed(seed) 850 for i := 0; i < numNodes; i++ { 851 n.AddNode(NewTree) 852 } 853 854 for !n.Finalized() && !n.Disagreement() { 855 n.Round() 856 } 857 858 require.True(n.Agreement()) 859 } 860 861 func TestSnowballFilterBinaryChildren(t *testing.T) { 862 require := require.New(t) 863 864 c0000 := ids.ID{0b00000000} 865 c1000 := ids.ID{0b00000001} 866 c0100 := ids.ID{0b00000010} 867 c0010 := ids.ID{0b00000100} 868 869 params := Parameters{ 870 K: 1, 871 AlphaPreference: 1, 872 AlphaConfidence: 1, 873 Beta: 2, 874 } 875 tree := NewTree(SnowballFactory, params, c0000) 876 877 require.Equal(initialUnaryDescription, tree.String()) 878 require.Equal(c0000, tree.Preference()) 879 require.False(tree.Finalized()) 880 881 tree.Add(c1000) 882 883 { 884 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 885 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256) 886 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 887 require.Equal(expected, tree.String()) 888 require.Equal(c0000, tree.Preference()) 889 require.False(tree.Finalized()) 890 } 891 892 tree.Add(c0010) 893 894 { 895 expected := `SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 0 896 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 2) 897 SB(Preference = 0, PreferenceStrength[0] = 0, PreferenceStrength[1] = 0, SF(Confidence = [0], Finalized = false, SL(Preference = 0))) Bit = 2 898 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 899 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 900 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 901 require.Equal(expected, tree.String()) 902 require.Equal(c0000, tree.Preference()) 903 require.False(tree.Finalized()) 904 } 905 906 c0000Bag := bag.Of(c0000) 907 require.True(tree.RecordPoll(c0000Bag)) 908 909 { 910 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 911 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [1, 2) 912 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 2 913 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [3, 256) 914 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 915 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 916 require.Equal(expected, tree.String()) 917 require.Equal(c0000, tree.Preference()) 918 require.False(tree.Finalized()) 919 } 920 921 tree.Add(c0100) 922 923 { 924 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 0 925 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 1 926 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 2 927 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [3, 256) 928 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 929 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [2, 256) 930 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [1, 256)` 931 require.Equal(expected, tree.String()) 932 require.Equal(c0000, tree.Preference()) 933 require.False(tree.Finalized()) 934 } 935 936 c0100Bag := bag.Of(c0100) 937 require.True(tree.RecordPoll(c0100Bag)) 938 939 { 940 expected := `SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 1, SF(Confidence = [1], Finalized = false, SL(Preference = 1))) Bit = 1 941 SB(Preference = 0, PreferenceStrength[0] = 1, PreferenceStrength[1] = 0, SF(Confidence = [1], Finalized = false, SL(Preference = 0))) Bit = 2 942 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [3, 256) 943 SB(PreferenceStrength = 0, SF(Confidence = [0], Finalized = false)) Bits = [3, 256) 944 SB(PreferenceStrength = 1, SF(Confidence = [1], Finalized = false)) Bits = [2, 256)` 945 require.Equal(expected, tree.String()) 946 require.Equal(c0000, tree.Preference()) 947 require.False(tree.Finalized()) 948 } 949 } 950 951 func TestSnowballRecordPreferencePollBinary(t *testing.T) { 952 require := require.New(t) 953 954 params := Parameters{ 955 K: 3, 956 AlphaPreference: 2, 957 AlphaConfidence: 3, 958 Beta: 2, 959 } 960 tree := NewTree(SnowballFactory, params, Red) 961 tree.Add(Blue) 962 require.Equal(Red, tree.Preference()) 963 require.False(tree.Finalized()) 964 965 threeBlue := bag.Of(Blue, Blue, Blue) 966 require.True(tree.RecordPoll(threeBlue)) 967 require.Equal(Blue, tree.Preference()) 968 require.False(tree.Finalized()) 969 970 twoRed := bag.Of(Red, Red) 971 require.True(tree.RecordPoll(twoRed)) 972 require.Equal(Blue, tree.Preference()) 973 require.False(tree.Finalized()) 974 975 threeRed := bag.Of(Red, Red, Red) 976 require.True(tree.RecordPoll(threeRed)) 977 require.Equal(Red, tree.Preference()) 978 require.False(tree.Finalized()) 979 980 require.True(tree.RecordPoll(threeRed)) 981 require.Equal(Red, tree.Preference()) 982 require.True(tree.Finalized()) 983 } 984 985 func TestSnowballRecordPreferencePollUnary(t *testing.T) { 986 require := require.New(t) 987 988 params := Parameters{ 989 K: 3, 990 AlphaPreference: 2, 991 AlphaConfidence: 3, 992 Beta: 2, 993 } 994 tree := NewTree(SnowballFactory, params, Red) 995 require.Equal(Red, tree.Preference()) 996 require.False(tree.Finalized()) 997 998 twoRed := bag.Of(Red, Red) 999 require.True(tree.RecordPoll(twoRed)) 1000 require.Equal(Red, tree.Preference()) 1001 require.False(tree.Finalized()) 1002 1003 tree.Add(Blue) 1004 1005 threeBlue := bag.Of(Blue, Blue, Blue) 1006 require.True(tree.RecordPoll(threeBlue)) 1007 require.Equal(Red, tree.Preference()) 1008 require.False(tree.Finalized()) 1009 1010 require.True(tree.RecordPoll(threeBlue)) 1011 require.Equal(Blue, tree.Preference()) 1012 require.True(tree.Finalized()) 1013 }