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 }