github.com/koko1123/flow-go-1@v0.29.6/storage/badger/dkg_state_test.go (about)

     1  package badger_test
     2  
     3  import (
     4  	"errors"
     5  	"math/rand"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/dgraph-io/badger/v3"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"github.com/koko1123/flow-go-1/model/flow"
    14  	"github.com/koko1123/flow-go-1/module/metrics"
    15  	"github.com/koko1123/flow-go-1/storage"
    16  	bstorage "github.com/koko1123/flow-go-1/storage/badger"
    17  	"github.com/koko1123/flow-go-1/utils/unittest"
    18  )
    19  
    20  func TestDKGState_DKGStarted(t *testing.T) {
    21  	unittest.RunWithTypedBadgerDB(t, bstorage.InitSecret, func(db *badger.DB) {
    22  		metrics := metrics.NewNoopCollector()
    23  		store, err := bstorage.NewDKGState(metrics, db)
    24  		require.NoError(t, err)
    25  
    26  		epochCounter := rand.Uint64()
    27  
    28  		// check dkg-started flag for non-existent epoch
    29  		t.Run("DKGStarted should default to false", func(t *testing.T) {
    30  			started, err := store.GetDKGStarted(rand.Uint64())
    31  			assert.NoError(t, err)
    32  			assert.False(t, started)
    33  		})
    34  
    35  		// store dkg-started flag for epoch
    36  		t.Run("should be able to set DKGStarted", func(t *testing.T) {
    37  			err = store.SetDKGStarted(epochCounter)
    38  			assert.NoError(t, err)
    39  		})
    40  
    41  		// retrieve flag for epoch
    42  		t.Run("should be able to read DKGStarted", func(t *testing.T) {
    43  			started, err := store.GetDKGStarted(epochCounter)
    44  			assert.NoError(t, err)
    45  			assert.True(t, started)
    46  		})
    47  	})
    48  }
    49  
    50  func TestDKGState_BeaconKeys(t *testing.T) {
    51  	unittest.RunWithTypedBadgerDB(t, bstorage.InitSecret, func(db *badger.DB) {
    52  		metrics := metrics.NewNoopCollector()
    53  		store, err := bstorage.NewDKGState(metrics, db)
    54  		require.NoError(t, err)
    55  
    56  		rand.Seed(time.Now().UnixNano())
    57  		epochCounter := rand.Uint64()
    58  
    59  		// attempt to get a non-existent key
    60  		t.Run("should error if retrieving non-existent key", func(t *testing.T) {
    61  			_, err = store.RetrieveMyBeaconPrivateKey(epochCounter)
    62  			assert.True(t, errors.Is(err, storage.ErrNotFound))
    63  		})
    64  
    65  		// attempt to store a nil key should fail (use DKGState.SetEndState(flow.DKGEndStateNoKey)
    66  		t.Run("should fail to store a nil key instead)", func(t *testing.T) {
    67  			err = store.InsertMyBeaconPrivateKey(epochCounter, nil)
    68  			assert.Error(t, err)
    69  		})
    70  
    71  		// store a key in db
    72  		expected := unittest.RandomBeaconPriv()
    73  		t.Run("should be able to store and read a key", func(t *testing.T) {
    74  			err = store.InsertMyBeaconPrivateKey(epochCounter, expected)
    75  			require.NoError(t, err)
    76  		})
    77  
    78  		// retrieve the key by epoch counter
    79  		t.Run("should be able to retrieve stored key", func(t *testing.T) {
    80  			actual, err := store.RetrieveMyBeaconPrivateKey(epochCounter)
    81  			require.NoError(t, err)
    82  			assert.Equal(t, expected, actual)
    83  		})
    84  
    85  		// test storing same key
    86  		t.Run("should fail to store a key twice", func(t *testing.T) {
    87  			err = store.InsertMyBeaconPrivateKey(epochCounter, expected)
    88  			require.True(t, errors.Is(err, storage.ErrAlreadyExists))
    89  		})
    90  	})
    91  }
    92  
    93  func TestDKGState_EndState(t *testing.T) {
    94  	unittest.RunWithTypedBadgerDB(t, bstorage.InitSecret, func(db *badger.DB) {
    95  		metrics := metrics.NewNoopCollector()
    96  		store, err := bstorage.NewDKGState(metrics, db)
    97  		require.NoError(t, err)
    98  
    99  		rand.Seed(time.Now().UnixNano())
   100  		epochCounter := rand.Uint64()
   101  		endState := flow.DKGEndStateNoKey
   102  
   103  		t.Run("should be able to store an end state", func(t *testing.T) {
   104  			err = store.SetDKGEndState(epochCounter, endState)
   105  			require.NoError(t, err)
   106  		})
   107  
   108  		t.Run("should be able to read an end state", func(t *testing.T) {
   109  			readEndState, err := store.GetDKGEndState(epochCounter)
   110  			require.NoError(t, err)
   111  			assert.Equal(t, endState, readEndState)
   112  		})
   113  	})
   114  }
   115  
   116  func TestSafeBeaconPrivateKeys(t *testing.T) {
   117  	unittest.RunWithTypedBadgerDB(t, bstorage.InitSecret, func(db *badger.DB) {
   118  		metrics := metrics.NewNoopCollector()
   119  		dkgState, err := bstorage.NewDKGState(metrics, db)
   120  		require.NoError(t, err)
   121  		safeKeys := bstorage.NewSafeBeaconPrivateKeys(dkgState)
   122  
   123  		t.Run("non-existent key - should error", func(t *testing.T) {
   124  			epochCounter := rand.Uint64()
   125  			key, safe, err := safeKeys.RetrieveMyBeaconPrivateKey(epochCounter)
   126  			assert.Nil(t, key)
   127  			assert.False(t, safe)
   128  			assert.Error(t, err)
   129  		})
   130  
   131  		t.Run("existent key, non-existent dkg end state - should error", func(t *testing.T) {
   132  			epochCounter := rand.Uint64()
   133  
   134  			// store a key
   135  			expected := unittest.RandomBeaconPriv().PrivateKey
   136  			err := dkgState.InsertMyBeaconPrivateKey(epochCounter, expected)
   137  			assert.NoError(t, err)
   138  
   139  			key, safe, err := safeKeys.RetrieveMyBeaconPrivateKey(epochCounter)
   140  			assert.Nil(t, key)
   141  			assert.False(t, safe)
   142  			assert.Error(t, err)
   143  		})
   144  
   145  		t.Run("existent key, unsuccessful dkg - not safe", func(t *testing.T) {
   146  			epochCounter := rand.Uint64()
   147  
   148  			// store a key
   149  			expected := unittest.RandomBeaconPriv().PrivateKey
   150  			err := dkgState.InsertMyBeaconPrivateKey(epochCounter, expected)
   151  			assert.NoError(t, err)
   152  			// mark dkg unsuccessful
   153  			err = dkgState.SetDKGEndState(epochCounter, flow.DKGEndStateInconsistentKey)
   154  			assert.NoError(t, err)
   155  
   156  			key, safe, err := safeKeys.RetrieveMyBeaconPrivateKey(epochCounter)
   157  			assert.Nil(t, key)
   158  			assert.False(t, safe)
   159  			assert.NoError(t, err)
   160  		})
   161  
   162  		t.Run("existent key, successful dkg - safe", func(t *testing.T) {
   163  			epochCounter := rand.Uint64()
   164  
   165  			// store a key
   166  			expected := unittest.RandomBeaconPriv().PrivateKey
   167  			err := dkgState.InsertMyBeaconPrivateKey(epochCounter, expected)
   168  			assert.NoError(t, err)
   169  			// mark dkg successful
   170  			err = dkgState.SetDKGEndState(epochCounter, flow.DKGEndStateSuccess)
   171  			assert.NoError(t, err)
   172  
   173  			key, safe, err := safeKeys.RetrieveMyBeaconPrivateKey(epochCounter)
   174  			assert.NotNil(t, key)
   175  			assert.True(t, expected.Equals(key))
   176  			assert.True(t, safe)
   177  			assert.NoError(t, err)
   178  		})
   179  	})
   180  }
   181  
   182  // TestSecretDBRequirement tests that the DKGState constructor will return an
   183  // error if instantiated using a database not marked with the correct type.
   184  func TestSecretDBRequirement(t *testing.T) {
   185  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
   186  		metrics := metrics.NewNoopCollector()
   187  		_, err := bstorage.NewDKGState(metrics, db)
   188  		require.Error(t, err)
   189  	})
   190  }