github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/core/roundstate_db_test.go (about)

     1  package core
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	blscrypto "github.com/ethereum/go-ethereum/crypto/bls"
     7  	"math/rand"
     8  	"testing"
     9  
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    12  	"github.com/ethereum/go-ethereum/consensus/istanbul/validator"
    13  )
    14  
    15  func TestRSDBRoundStateDB(t *testing.T) {
    16  	pubkey1 := blscrypto.SerializedPublicKey{1, 2, 3}
    17  	pubkey2 := blscrypto.SerializedPublicKey{3, 1, 4}
    18  	dummyRoundState := func() RoundState {
    19  		valSet := validator.NewSet([]istanbul.ValidatorData{
    20  			{Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: pubkey1},
    21  			{Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: pubkey2},
    22  		})
    23  		return newRoundState(newView(2, 1), valSet, valSet.GetByIndex(0))
    24  	}
    25  
    26  	t.Run("Should save view & roundState", func(t *testing.T) {
    27  		rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{withGarbageCollector: false})
    28  		rs := dummyRoundState()
    29  		err := rsdb.UpdateLastRoundState(rs)
    30  		finishOnError(t, err)
    31  
    32  		view, err := rsdb.GetLastView()
    33  		finishOnError(t, err)
    34  		assertEqualView(t, view, rs.View())
    35  
    36  		savedRs, err := rsdb.GetRoundStateFor(view)
    37  		finishOnError(t, err)
    38  		assertEqualRoundState(t, savedRs, rs)
    39  	})
    40  
    41  	t.Run("Should save view from last saved roundState", func(t *testing.T) {
    42  		rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{withGarbageCollector: false})
    43  		rs := dummyRoundState()
    44  		err := rsdb.UpdateLastRoundState(rs)
    45  		finishOnError(t, err)
    46  		rs.StartNewSequence(common.Big32, rs.ValidatorSet(), rs.ValidatorSet().GetByIndex(1), rs.ParentCommits())
    47  		err = rsdb.UpdateLastRoundState(rs)
    48  		finishOnError(t, err)
    49  
    50  		view, err := rsdb.GetLastView()
    51  		finishOnError(t, err)
    52  		assertEqualView(t, view, rs.View())
    53  	})
    54  
    55  }
    56  
    57  func TestRSDBDeleteEntriesOlderThan(t *testing.T) {
    58  	pubkey1 := blscrypto.SerializedPublicKey{1, 2, 3}
    59  	pubkey2 := blscrypto.SerializedPublicKey{3, 1, 4}
    60  	createRoundState := func(view *istanbul.View) RoundState {
    61  		valSet := validator.NewSet([]istanbul.ValidatorData{
    62  			{Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: pubkey1},
    63  			{Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: pubkey2},
    64  		})
    65  		return newRoundState(view, valSet, valSet.GetByIndex(0))
    66  	}
    67  
    68  	rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{withGarbageCollector: false})
    69  	for seq := uint64(1); seq <= 10; seq++ {
    70  		for r := uint64(0); r < 10; r++ {
    71  			rs := createRoundState(newView(seq, r))
    72  			err := rsdb.UpdateLastRoundState(rs)
    73  			finishOnError(t, err)
    74  		}
    75  	}
    76  
    77  	// Will delete all entries from seq 1
    78  	count, err := rsdb.(*roundStateDBImpl).deleteEntriesOlderThan(newView(2, 0))
    79  	if err != nil {
    80  		t.Fatalf("Error %v", err)
    81  	}
    82  	if count != 10 {
    83  		t.Fatalf("Expected 10 deleted entries but got %d", count)
    84  	}
    85  
    86  	// Will delete all entries from seq 2,3 and seq 4 until round 5
    87  	count, err = rsdb.(*roundStateDBImpl).deleteEntriesOlderThan(newView(4, 5))
    88  	if err != nil {
    89  		t.Fatalf("Error %v", err)
    90  	}
    91  	if count != 25 {
    92  		t.Fatalf("Expected 10 deleted entries but got %d", count)
    93  	}
    94  
    95  }
    96  
    97  func TestRSDBKeyEncodingOrder(t *testing.T) {
    98  	iterations := 1000
    99  
   100  	t.Run("ViewKey enconding should decode the same view", func(t *testing.T) {
   101  		for i := 0; i < iterations; i++ {
   102  			view := newView(rand.Uint64(), rand.Uint64())
   103  			key := view2Key(view)
   104  			parsedView := key2View(key)
   105  			if view.Cmp(parsedView) != 0 {
   106  				t.Errorf("parsedView != view: %v != %v", parsedView, view)
   107  			}
   108  		}
   109  	})
   110  
   111  	t.Run("ViewKey enconding should maintain sort order", func(t *testing.T) {
   112  		for i := 0; i < iterations; i++ {
   113  			viewA := newView(rand.Uint64(), rand.Uint64())
   114  			keyA := view2Key(viewA)
   115  
   116  			viewB := newView(rand.Uint64(), rand.Uint64())
   117  			keyB := view2Key(viewB)
   118  
   119  			if viewA.Cmp(viewB) != bytes.Compare(keyA, keyB) {
   120  				t.Errorf("view order != key order (viewA: %v, viewB: %v, keyA:%v, keyB:%v )",
   121  					viewA,
   122  					viewB,
   123  					hex.EncodeToString(keyA),
   124  					hex.EncodeToString(keyB),
   125  				)
   126  
   127  			}
   128  		}
   129  	})
   130  }
   131  
   132  func TestRSDBGetOldestValidView(t *testing.T) {
   133  	pubkey1 := blscrypto.SerializedPublicKey{1, 2, 3}
   134  	pubkey2 := blscrypto.SerializedPublicKey{3, 1, 4}
   135  	valSet := validator.NewSet([]istanbul.ValidatorData{
   136  		{Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: pubkey1},
   137  		{Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: pubkey2},
   138  	})
   139  	sequencesToSave := uint64(100)
   140  	runTestCase := func(name string, viewToStore, expectedView *istanbul.View) {
   141  		t.Run(name, func(t *testing.T) {
   142  			rsdb, _ := newRoundStateDB("", &RoundStateDBOptions{
   143  				withGarbageCollector: false,
   144  				sequencesToSave:      sequencesToSave,
   145  			})
   146  
   147  			if viewToStore != nil {
   148  				t.Logf("Saving RoundState")
   149  				err := rsdb.UpdateLastRoundState(newRoundState(viewToStore, valSet, valSet.GetByIndex(0)))
   150  				if err != nil {
   151  					t.Fatalf("UpdateLastRoundState error: %v", err)
   152  				}
   153  			}
   154  
   155  			view, err := rsdb.GetOldestValidView()
   156  			if err != nil {
   157  				t.Fatalf("GetOldestValidView error: %v", err)
   158  			}
   159  			if view.Cmp(expectedView) != 0 {
   160  				t.Errorf("Expected %v, got %v", expectedView, view)
   161  			}
   162  		})
   163  	}
   164  
   165  	runTestCase("When Nothing Stored", nil, newView(0, 0))
   166  	runTestCase("When StoredSequence < sequencesToSave", newView(sequencesToSave-1, 90), newView(0, 0))
   167  	runTestCase("When StoredSequence == sequencesToSave", newView(sequencesToSave, 90), newView(0, 0))
   168  	runTestCase("When StoredSequence > sequencesToSave", newView(sequencesToSave+1, 90), newView(1, 0))
   169  	runTestCase("When StoredSequence >> sequencesToSave", newView(sequencesToSave+1000, 90), newView(1000, 0))
   170  }