github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/acm/validator/validators.go (about) 1 package validator 2 3 import ( 4 "math/big" 5 6 "github.com/hyperledger/burrow/crypto" 7 ) 8 9 type Writer interface { 10 SetPower(id *crypto.PublicKey, power *big.Int) (flow *big.Int, err error) 11 } 12 13 type Reader interface { 14 Power(id crypto.Address) (*big.Int, error) 15 } 16 17 type Iterable interface { 18 IterateValidators(func(id crypto.Addressable, power *big.Int) error) error 19 } 20 21 type IterableReader interface { 22 Reader 23 Iterable 24 } 25 26 type ReaderWriter interface { 27 Reader 28 Writer 29 } 30 31 type IterableReaderWriter interface { 32 ReaderWriter 33 Iterable 34 } 35 36 type History interface { 37 ValidatorChanges(blocksAgo int) IterableReader 38 Validators(blocksAgo int) IterableReader 39 } 40 41 func AddPower(vs ReaderWriter, id *crypto.PublicKey, power *big.Int) error { 42 // Current power + power 43 currentPower, err := vs.Power(id.GetAddress()) 44 if err != nil { 45 return err 46 } 47 _, err = vs.SetPower(id, new(big.Int).Add(currentPower, power)) 48 return err 49 } 50 51 func SubtractPower(vs ReaderWriter, id *crypto.PublicKey, power *big.Int) error { 52 currentPower, err := vs.Power(id.GetAddress()) 53 if err != nil { 54 return err 55 } 56 _, err = vs.SetPower(id, new(big.Int).Sub(currentPower, power)) 57 return err 58 } 59 60 // Returns the asymmetric difference, diff, between two Sets such that applying diff to before results in after 61 func Diff(before, after IterableReader) (*Set, error) { 62 diff := NewSet() 63 err := after.IterateValidators(func(id crypto.Addressable, powerAfter *big.Int) error { 64 powerBefore, err := before.Power(id.GetAddress()) 65 if err != nil { 66 return err 67 } 68 // Exclude any powers from before that much after 69 if powerBefore.Cmp(powerAfter) != 0 { 70 diff.ChangePower(id.GetPublicKey(), powerAfter) 71 } 72 return nil 73 }) 74 if err != nil { 75 return nil, err 76 } 77 // Make sure to zero any validators in before but not in after 78 err = before.IterateValidators(func(id crypto.Addressable, powerBefore *big.Int) error { 79 powerAfter, err := after.Power(id.GetAddress()) 80 if err != nil { 81 return err 82 } 83 // If there is a difference value then add to diff 84 if powerAfter.Cmp(powerBefore) != 0 { 85 diff.ChangePower(id.GetPublicKey(), powerAfter) 86 } 87 return nil 88 }) 89 if err != nil { 90 return nil, err 91 } 92 return diff, nil 93 } 94 95 func Write(vs Writer, vsOther Iterable) error { 96 return vsOther.IterateValidators(func(id crypto.Addressable, power *big.Int) error { 97 _, err := vs.SetPower(id.GetPublicKey(), power) 98 return err 99 }) 100 } 101 102 // Adds vsOther to vs 103 func Add(vs ReaderWriter, vsOther Iterable) error { 104 return vsOther.IterateValidators(func(id crypto.Addressable, power *big.Int) error { 105 return AddPower(vs, id.GetPublicKey(), power) 106 }) 107 } 108 109 // Subtracts vsOther from vs 110 func Subtract(vs ReaderWriter, vsOther Iterable) error { 111 return vsOther.IterateValidators(func(id crypto.Addressable, power *big.Int) error { 112 return SubtractPower(vs, id.GetPublicKey(), power) 113 }) 114 } 115 116 func copySet(trim bool, vss []Iterable) *Set { 117 vsCopy := newSet() 118 vsCopy.trim = trim 119 for _, vs := range vss { 120 vs.IterateValidators(func(id crypto.Addressable, power *big.Int) error { 121 vsCopy.ChangePower(id.GetPublicKey(), power) 122 return nil 123 }) 124 } 125 return vsCopy 126 } 127 128 // Copy each of iterable in vss into a new Set - note any iterations errors thrown by the iterable itself will be swallowed 129 // Use Write instead if source iterables may error 130 func Copy(vss ...Iterable) *Set { 131 return copySet(false, vss) 132 } 133 134 func CopyTrim(vss ...Iterable) *Set { 135 return copySet(true, vss) 136 }