github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/acm/validator/ring_test.go (about)

     1  package validator
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math/big"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestValidatorsRing_SetPower(t *testing.T) {
    14  	vsBase := NewSet()
    15  	powAInitial := int64(10000)
    16  	vsBase.ChangePower(pubA, big.NewInt(powAInitial))
    17  
    18  	vs := Copy(vsBase)
    19  	vw := NewRing(vs, 3)
    20  
    21  	// Just allowable validator tide
    22  	var powA, powB, powC int64 = 7000, 23, 309
    23  	powerChange, totalFlow, err := alterPowers(t, vw, powA, powB, powC)
    24  	require.NoError(t, err)
    25  	assert.Equal(t, big.NewInt(powA+powB+powC-powAInitial), powerChange)
    26  	assert.Equal(t, big.NewInt(powAInitial/3-1), totalFlow)
    27  
    28  	// This one is not
    29  	vs = Copy(vsBase)
    30  	vw = NewRing(vs, 5)
    31  	powA, powB, powC = 7000, 23, 310
    32  	_, _, err = alterPowers(t, vw, powA, powB, powC)
    33  	require.Error(t, err)
    34  
    35  	powA, powB, powC = 7000, 23, 309
    36  	powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC)
    37  	require.NoError(t, err)
    38  	assert.Equal(t, big.NewInt(powA+powB+powC-powAInitial), powerChange)
    39  	assert.Equal(t, big.NewInt(powAInitial/3-1), totalFlow)
    40  
    41  	powA, powB, powC = 7000, 23, 309
    42  	powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC)
    43  	require.NoError(t, err)
    44  	assertZero(t, powerChange)
    45  	assertZero(t, totalFlow)
    46  
    47  	_, err = vw.SetPower(pubA, big.NewInt(8000))
    48  	assert.NoError(t, err)
    49  
    50  	// Should fail - not enough flow left
    51  	_, err = vw.SetPower(pubB, big.NewInt(2000))
    52  	assert.Error(t, err)
    53  
    54  	// Take a bit off should work
    55  	_, err = vw.SetPower(pubA, big.NewInt(7000))
    56  	assert.NoError(t, err)
    57  
    58  	_, err = vw.SetPower(pubB, big.NewInt(2000))
    59  	assert.NoError(t, err)
    60  	_, _, err = vw.Rotate()
    61  	require.NoError(t, err)
    62  
    63  	powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC)
    64  	require.NoError(t, err)
    65  	assert.Equal(t, big.NewInt(-1977), powerChange)
    66  	assert.Equal(t, big.NewInt(1977), totalFlow)
    67  
    68  	powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC)
    69  	require.NoError(t, err)
    70  	assertZero(t, powerChange)
    71  	assert.Equal(t, big0, totalFlow)
    72  
    73  	powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC)
    74  	require.NoError(t, err)
    75  	assertZero(t, powerChange)
    76  	assert.Equal(t, big0, totalFlow)
    77  }
    78  
    79  func TestRing_Rotate(t *testing.T) {
    80  	ring := NewRing(nil, 3)
    81  	_, err := ring.SetPower(pubA, big.NewInt(234))
    82  	require.NoError(t, err)
    83  	fmt.Println(printBuckets(ring))
    84  	_, _, err = ring.Rotate()
    85  	require.NoError(t, err)
    86  
    87  	_, err = ring.SetPower(pubB, big.NewInt(40))
    88  	require.NoError(t, err)
    89  	fmt.Println(printBuckets(ring))
    90  	_, _, err = ring.Rotate()
    91  	require.NoError(t, err)
    92  	fmt.Println(printBuckets(ring))
    93  
    94  	_, err = ring.SetPower(pubC, big.NewInt(90))
    95  	require.NoError(t, err)
    96  	fmt.Println(printBuckets(ring))
    97  	_, _, err = ring.Rotate()
    98  	require.NoError(t, err)
    99  	fmt.Println(printBuckets(ring))
   100  
   101  	fmt.Println(ring.ValidatorChanges(1))
   102  }
   103  
   104  func printBuckets(ring *Ring) string {
   105  	buf := new(bytes.Buffer)
   106  	for i, b := range ring.OrderedBuckets() {
   107  		buf.WriteString(fmt.Sprintf("%d: ", i))
   108  		buf.WriteString(b.String())
   109  		buf.WriteString("\n")
   110  	}
   111  	return buf.String()
   112  }
   113  
   114  func alterPowers(t testing.TB, vw *Ring, powA, powB, powC int64) (powerChange, totalFlow *big.Int, err error) {
   115  	_, err = vw.SetPower(pubA, big.NewInt(powA))
   116  	if err != nil {
   117  		return nil, nil, err
   118  	}
   119  	_, err = vw.SetPower(pubB, big.NewInt(powB))
   120  	if err != nil {
   121  		return nil, nil, err
   122  	}
   123  	_, err = vw.SetPower(pubC, big.NewInt(powC))
   124  	if err != nil {
   125  		return nil, nil, err
   126  	}
   127  	maxFlow := vw.Head().Previous.MaxFlow()
   128  	powerChange, totalFlow, err = vw.Rotate()
   129  	require.NoError(t, err)
   130  	// totalFlow > maxFlow
   131  	if totalFlow.Cmp(maxFlow) == 1 {
   132  		return powerChange, totalFlow, fmt.Errorf("totalFlow (%v) exceeds maxFlow (%v)", totalFlow, maxFlow)
   133  	}
   134  
   135  	return powerChange, totalFlow, nil
   136  }
   137  
   138  // Since we have -0 and 0 with big.Int due to its representation with a neg flag
   139  func assertZero(t testing.TB, i *big.Int) {
   140  	assert.True(t, big0.Cmp(i) == 0, "expected 0 but got %v", i)
   141  }