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  }