github.com/evdatsion/aphelion-dpos-bft@v0.32.1/lite/dynamic_verifier_test.go (about)

     1  package lite
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	dbm "github.com/evdatsion/aphelion-dpos-bft/libs/db"
    12  	log "github.com/evdatsion/aphelion-dpos-bft/libs/log"
    13  	"github.com/evdatsion/aphelion-dpos-bft/types"
    14  )
    15  
    16  func TestInquirerValidPath(t *testing.T) {
    17  	assert, require := assert.New(t), require.New(t)
    18  	trust := NewDBProvider("trust", dbm.NewMemDB())
    19  	source := NewDBProvider("source", dbm.NewMemDB())
    20  
    21  	// Set up the validators to generate test blocks.
    22  	var vote int64 = 10
    23  	keys := genPrivKeys(5)
    24  	nkeys := keys.Extend(1)
    25  
    26  	// Construct a bunch of commits, each with one more height than the last.
    27  	chainID := "inquiry-test"
    28  	consHash := []byte("params")
    29  	resHash := []byte("results")
    30  	count := 50
    31  	fcz := make([]FullCommit, count)
    32  	for i := 0; i < count; i++ {
    33  		vals := keys.ToValidators(vote, 0)
    34  		nextVals := nkeys.ToValidators(vote, 0)
    35  		h := int64(1 + i)
    36  		appHash := []byte(fmt.Sprintf("h=%d", h))
    37  		fcz[i] = keys.GenFullCommit(
    38  			chainID, h, nil,
    39  			vals, nextVals,
    40  			appHash, consHash, resHash, 0, len(keys))
    41  		// Extend the keys by 1 each time.
    42  		keys = nkeys
    43  		nkeys = nkeys.Extend(1)
    44  	}
    45  
    46  	// Initialize a Verifier with the initial state.
    47  	err := trust.SaveFullCommit(fcz[0])
    48  	require.Nil(err)
    49  	cert := NewDynamicVerifier(chainID, trust, source)
    50  	cert.SetLogger(log.TestingLogger())
    51  
    52  	// This should fail validation:
    53  	sh := fcz[count-1].SignedHeader
    54  	err = cert.Verify(sh)
    55  	require.NotNil(err)
    56  
    57  	// Adding a few commits in the middle should be insufficient.
    58  	for i := 10; i < 13; i++ {
    59  		err := source.SaveFullCommit(fcz[i])
    60  		require.Nil(err)
    61  	}
    62  	err = cert.Verify(sh)
    63  	assert.NotNil(err)
    64  
    65  	// With more info, we succeed.
    66  	for i := 0; i < count; i++ {
    67  		err := source.SaveFullCommit(fcz[i])
    68  		require.Nil(err)
    69  	}
    70  	err = cert.Verify(sh)
    71  	assert.Nil(err, "%+v", err)
    72  }
    73  
    74  func TestDynamicVerify(t *testing.T) {
    75  	trust := NewDBProvider("trust", dbm.NewMemDB())
    76  	source := NewDBProvider("source", dbm.NewMemDB())
    77  
    78  	// 10 commits with one valset, 1 to change,
    79  	// 10 commits with the next one
    80  	n1, n2 := 10, 10
    81  	nCommits := n1 + n2 + 1
    82  	maxHeight := int64(nCommits)
    83  	fcz := make([]FullCommit, nCommits)
    84  
    85  	// gen the 2 val sets
    86  	chainID := "dynamic-verifier"
    87  	power := int64(10)
    88  	keys1 := genPrivKeys(5)
    89  	vals1 := keys1.ToValidators(power, 0)
    90  	keys2 := genPrivKeys(5)
    91  	vals2 := keys2.ToValidators(power, 0)
    92  
    93  	// make some commits with the first
    94  	for i := 0; i < n1; i++ {
    95  		fcz[i] = makeFullCommit(int64(i), keys1, vals1, vals1, chainID)
    96  	}
    97  
    98  	// update the val set
    99  	fcz[n1] = makeFullCommit(int64(n1), keys1, vals1, vals2, chainID)
   100  
   101  	// make some commits with the new one
   102  	for i := n1 + 1; i < nCommits; i++ {
   103  		fcz[i] = makeFullCommit(int64(i), keys2, vals2, vals2, chainID)
   104  	}
   105  
   106  	// Save everything in the source
   107  	for _, fc := range fcz {
   108  		source.SaveFullCommit(fc)
   109  	}
   110  
   111  	// Initialize a Verifier with the initial state.
   112  	err := trust.SaveFullCommit(fcz[0])
   113  	require.Nil(t, err)
   114  	ver := NewDynamicVerifier(chainID, trust, source)
   115  	ver.SetLogger(log.TestingLogger())
   116  
   117  	// fetch the latest from the source
   118  	latestFC, err := source.LatestFullCommit(chainID, 1, maxHeight)
   119  	require.NoError(t, err)
   120  
   121  	// try to update to the latest
   122  	err = ver.Verify(latestFC.SignedHeader)
   123  	require.NoError(t, err)
   124  
   125  }
   126  
   127  func makeFullCommit(height int64, keys privKeys, vals, nextVals *types.ValidatorSet, chainID string) FullCommit {
   128  	height += 1
   129  	consHash := []byte("special-params")
   130  	appHash := []byte(fmt.Sprintf("h=%d", height))
   131  	resHash := []byte(fmt.Sprintf("res=%d", height))
   132  	return keys.GenFullCommit(
   133  		chainID, height, nil,
   134  		vals, nextVals,
   135  		appHash, consHash, resHash, 0, len(keys))
   136  }
   137  
   138  func TestInquirerVerifyHistorical(t *testing.T) {
   139  	assert, require := assert.New(t), require.New(t)
   140  	trust := NewDBProvider("trust", dbm.NewMemDB())
   141  	source := NewDBProvider("source", dbm.NewMemDB())
   142  
   143  	// Set up the validators to generate test blocks.
   144  	var vote int64 = 10
   145  	keys := genPrivKeys(5)
   146  	nkeys := keys.Extend(1)
   147  
   148  	// Construct a bunch of commits, each with one more height than the last.
   149  	chainID := "inquiry-test"
   150  	count := 10
   151  	consHash := []byte("special-params")
   152  	fcz := make([]FullCommit, count)
   153  	for i := 0; i < count; i++ {
   154  		vals := keys.ToValidators(vote, 0)
   155  		nextVals := nkeys.ToValidators(vote, 0)
   156  		h := int64(1 + i)
   157  		appHash := []byte(fmt.Sprintf("h=%d", h))
   158  		resHash := []byte(fmt.Sprintf("res=%d", h))
   159  		fcz[i] = keys.GenFullCommit(
   160  			chainID, h, nil,
   161  			vals, nextVals,
   162  			appHash, consHash, resHash, 0, len(keys))
   163  		// Extend the keys by 1 each time.
   164  		keys = nkeys
   165  		nkeys = nkeys.Extend(1)
   166  	}
   167  
   168  	// Initialize a Verifier with the initial state.
   169  	err := trust.SaveFullCommit(fcz[0])
   170  	require.Nil(err)
   171  	cert := NewDynamicVerifier(chainID, trust, source)
   172  	cert.SetLogger(log.TestingLogger())
   173  
   174  	// Store a few full commits as trust.
   175  	for _, i := range []int{2, 5} {
   176  		trust.SaveFullCommit(fcz[i])
   177  	}
   178  
   179  	// See if we can jump forward using trusted full commits.
   180  	// Souce doesn't have fcz[9] so cert.LastTrustedHeight wont' change.
   181  	err = source.SaveFullCommit(fcz[7])
   182  	require.Nil(err, "%+v", err)
   183  	sh := fcz[8].SignedHeader
   184  	err = cert.Verify(sh)
   185  	require.Nil(err, "%+v", err)
   186  	assert.Equal(fcz[7].Height(), cert.LastTrustedHeight())
   187  	fc_, err := trust.LatestFullCommit(chainID, fcz[8].Height(), fcz[8].Height())
   188  	require.NotNil(err, "%+v", err)
   189  	assert.Equal(fc_, (FullCommit{}))
   190  
   191  	// With fcz[9] Verify will update last trusted height.
   192  	err = source.SaveFullCommit(fcz[9])
   193  	require.Nil(err, "%+v", err)
   194  	sh = fcz[8].SignedHeader
   195  	err = cert.Verify(sh)
   196  	require.Nil(err, "%+v", err)
   197  	assert.Equal(fcz[8].Height(), cert.LastTrustedHeight())
   198  	fc_, err = trust.LatestFullCommit(chainID, fcz[8].Height(), fcz[8].Height())
   199  	require.Nil(err, "%+v", err)
   200  	assert.Equal(fc_.Height(), fcz[8].Height())
   201  
   202  	// Add access to all full commits via untrusted source.
   203  	for i := 0; i < count; i++ {
   204  		err := source.SaveFullCommit(fcz[i])
   205  		require.Nil(err)
   206  	}
   207  
   208  	// Try to check an unknown seed in the past.
   209  	sh = fcz[3].SignedHeader
   210  	err = cert.Verify(sh)
   211  	require.Nil(err, "%+v", err)
   212  	assert.Equal(fcz[8].Height(), cert.LastTrustedHeight())
   213  
   214  	// Jump all the way forward again.
   215  	sh = fcz[count-1].SignedHeader
   216  	err = cert.Verify(sh)
   217  	require.Nil(err, "%+v", err)
   218  	assert.Equal(fcz[9].Height(), cert.LastTrustedHeight())
   219  }
   220  
   221  func TestConcurrencyInquirerVerify(t *testing.T) {
   222  	_, require := assert.New(t), require.New(t)
   223  	trust := NewDBProvider("trust", dbm.NewMemDB()).SetLimit(10)
   224  	source := NewDBProvider("source", dbm.NewMemDB())
   225  
   226  	// Set up the validators to generate test blocks.
   227  	var vote int64 = 10
   228  	keys := genPrivKeys(5)
   229  	nkeys := keys.Extend(1)
   230  
   231  	// Construct a bunch of commits, each with one more height than the last.
   232  	chainID := "inquiry-test"
   233  	count := 10
   234  	consHash := []byte("special-params")
   235  	fcz := make([]FullCommit, count)
   236  	for i := 0; i < count; i++ {
   237  		vals := keys.ToValidators(vote, 0)
   238  		nextVals := nkeys.ToValidators(vote, 0)
   239  		h := int64(1 + i)
   240  		appHash := []byte(fmt.Sprintf("h=%d", h))
   241  		resHash := []byte(fmt.Sprintf("res=%d", h))
   242  		fcz[i] = keys.GenFullCommit(
   243  			chainID, h, nil,
   244  			vals, nextVals,
   245  			appHash, consHash, resHash, 0, len(keys))
   246  		// Extend the keys by 1 each time.
   247  		keys = nkeys
   248  		nkeys = nkeys.Extend(1)
   249  	}
   250  
   251  	// Initialize a Verifier with the initial state.
   252  	err := trust.SaveFullCommit(fcz[0])
   253  	require.Nil(err)
   254  	cert := NewDynamicVerifier(chainID, trust, source)
   255  	cert.SetLogger(log.TestingLogger())
   256  
   257  	err = source.SaveFullCommit(fcz[7])
   258  	require.Nil(err, "%+v", err)
   259  	err = source.SaveFullCommit(fcz[8])
   260  	require.Nil(err, "%+v", err)
   261  	sh := fcz[8].SignedHeader
   262  
   263  	var wg sync.WaitGroup
   264  	count = 100
   265  	errList := make([]error, count)
   266  	for i := 0; i < count; i++ {
   267  		wg.Add(1)
   268  		go func(index int) {
   269  			errList[index] = cert.Verify(sh)
   270  			defer wg.Done()
   271  		}(i)
   272  	}
   273  	wg.Wait()
   274  	for _, err := range errList {
   275  		require.Nil(err)
   276  	}
   277  }