github.com/MetalBlockchain/metalgo@v1.11.9/snow/consensus/snowball/unary_snowflake.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package snowball 5 6 import ( 7 "fmt" 8 "slices" 9 ) 10 11 var _ Unary = (*unarySnowflake)(nil) 12 13 func newUnarySnowflake(alphaPreference int, terminationConditions []terminationCondition) unarySnowflake { 14 return unarySnowflake{ 15 alphaPreference: alphaPreference, 16 terminationConditions: terminationConditions, 17 confidence: make([]int, len(terminationConditions)), 18 } 19 } 20 21 // unarySnowflake is the implementation of a unary snowflake instance 22 // Invariant: 23 // len(terminationConditions) == len(confidence) 24 // terminationConditions[i].alphaConfidence < terminationConditions[i+1].alphaConfidence 25 // terminationConditions[i].beta <= terminationConditions[i+1].beta 26 // confidence[i] >= confidence[i+1] (except after finalizing due to early termination) 27 type unarySnowflake struct { 28 // alphaPreference is the threshold required to update the preference 29 alphaPreference int 30 31 // terminationConditions gives the ascending ordered list of alphaConfidence values 32 // required to increment the corresponding confidence counter. 33 // The corresponding beta values give the threshold required to finalize this instance. 34 terminationConditions []terminationCondition 35 36 // confidence is the number of consecutive succcessful polls for a given 37 // alphaConfidence threshold. 38 // This instance finalizes when confidence[i] >= terminationConditions[i].beta for any i 39 confidence []int 40 41 // finalized prevents the state from changing after the required number of 42 // consecutive polls has been reached 43 finalized bool 44 } 45 46 func (sf *unarySnowflake) RecordPoll(count int) { 47 for i, terminationCondition := range sf.terminationConditions { 48 // If I did not reach this alpha threshold, I did not 49 // reach any more alpha thresholds. 50 // Clear the remaining confidence counters. 51 if count < terminationCondition.alphaConfidence { 52 clear(sf.confidence[i:]) 53 return 54 } 55 56 // I reached this alpha threshold, increment the confidence counter 57 // and check if I can finalize. 58 sf.confidence[i]++ 59 if sf.confidence[i] >= terminationCondition.beta { 60 sf.finalized = true 61 return 62 } 63 } 64 } 65 66 func (sf *unarySnowflake) RecordUnsuccessfulPoll() { 67 clear(sf.confidence) 68 } 69 70 func (sf *unarySnowflake) Finalized() bool { 71 return sf.finalized 72 } 73 74 func (sf *unarySnowflake) Extend(choice int) Binary { 75 return &binarySnowflake{ 76 binarySlush: binarySlush{preference: choice}, 77 confidence: slices.Clone(sf.confidence), 78 alphaPreference: sf.alphaPreference, 79 terminationConditions: sf.terminationConditions, 80 finalized: sf.finalized, 81 } 82 } 83 84 func (sf *unarySnowflake) Clone() Unary { 85 newSnowflake := *sf 86 newSnowflake.confidence = slices.Clone(sf.confidence) 87 return &newSnowflake 88 } 89 90 func (sf *unarySnowflake) String() string { 91 return fmt.Sprintf("SF(Confidence = %v, Finalized = %v)", 92 sf.confidence, 93 sf.finalized) 94 }