tendermint/lite/inquiring_certifier_test.go
Adrian Brink 32311acd01 Vulnerability in light client proxy (#1081)
* Vulnerability in light client proxy

When calling GetCertifiedCommit the light client proxy would call
Certify and even on error return the Commit as if it had been correctly
certified.

Now it returns the error correctly and returns an empty Commit on error.

* Improve names for clarity

The lite package now contains StaticCertifier, DynamicCertifier and
InqueringCertifier. This also changes the method receivers from one
letter to two letter names, which will make future refactoring easier
and follows the coding standards.

* Fix test failures

* Rename files

* remove dead code
2018-01-09 10:36:11 -06:00

174 lines
4.8 KiB
Go

// nolint: vetshadow
package lite_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/lite"
)
func TestInquirerValidPath(t *testing.T) {
assert, require := assert.New(t), require.New(t)
trust := lite.NewMemStoreProvider()
source := lite.NewMemStoreProvider()
// set up the validators to generate test blocks
var vote int64 = 10
keys := lite.GenValKeys(5)
// construct a bunch of commits, each with one more height than the last
chainID := "inquiry-test"
consHash := []byte("params")
resHash := []byte("results")
count := 50
commits := make([]lite.FullCommit, count)
for i := 0; i < count; i++ {
// extend the keys by 1 each time
keys = keys.Extend(1)
vals := keys.ToValidators(vote, 0)
h := int64(20 + 10*i)
appHash := []byte(fmt.Sprintf("h=%d", h))
commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, consHash, resHash, 0,
len(keys))
}
// initialize a certifier with the initial state
cert, err := lite.NewInquiringCertifier(chainID, commits[0], trust, source)
require.Nil(err)
// this should fail validation....
commit := commits[count-1].Commit
err = cert.Certify(commit)
require.NotNil(err)
// adding a few commits in the middle should be insufficient
for i := 10; i < 13; i++ {
err := source.StoreCommit(commits[i])
require.Nil(err)
}
err = cert.Certify(commit)
assert.NotNil(err)
// with more info, we succeed
for i := 0; i < count; i++ {
err := source.StoreCommit(commits[i])
require.Nil(err)
}
err = cert.Certify(commit)
assert.Nil(err, "%+v", err)
}
func TestInquirerMinimalPath(t *testing.T) {
assert, require := assert.New(t), require.New(t)
trust := lite.NewMemStoreProvider()
source := lite.NewMemStoreProvider()
// set up the validators to generate test blocks
var vote int64 = 10
keys := lite.GenValKeys(5)
// construct a bunch of commits, each with one more height than the last
chainID := "minimal-path"
consHash := []byte("other-params")
count := 12
commits := make([]lite.FullCommit, count)
for i := 0; i < count; i++ {
// extend the validators, so we are just below 2/3
keys = keys.Extend(len(keys)/2 - 1)
vals := keys.ToValidators(vote, 0)
h := int64(5 + 10*i)
appHash := []byte(fmt.Sprintf("h=%d", h))
resHash := []byte(fmt.Sprintf("res=%d", h))
commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, consHash, resHash, 0,
len(keys))
}
// initialize a certifier with the initial state
cert, _ := lite.NewInquiringCertifier(chainID, commits[0], trust, source)
// this should fail validation....
commit := commits[count-1].Commit
err := cert.Certify(commit)
require.NotNil(err)
// add a few seed in the middle should be insufficient
for i := 5; i < 8; i++ {
err := source.StoreCommit(commits[i])
require.Nil(err)
}
err = cert.Certify(commit)
assert.NotNil(err)
// with more info, we succeed
for i := 0; i < count; i++ {
err := source.StoreCommit(commits[i])
require.Nil(err)
}
err = cert.Certify(commit)
assert.Nil(err, "%+v", err)
}
func TestInquirerVerifyHistorical(t *testing.T) {
assert, require := assert.New(t), require.New(t)
trust := lite.NewMemStoreProvider()
source := lite.NewMemStoreProvider()
// set up the validators to generate test blocks
var vote int64 = 10
keys := lite.GenValKeys(5)
// construct a bunch of commits, each with one more height than the last
chainID := "inquiry-test"
count := 10
consHash := []byte("special-params")
commits := make([]lite.FullCommit, count)
for i := 0; i < count; i++ {
// extend the keys by 1 each time
keys = keys.Extend(1)
vals := keys.ToValidators(vote, 0)
h := int64(20 + 10*i)
appHash := []byte(fmt.Sprintf("h=%d", h))
resHash := []byte(fmt.Sprintf("res=%d", h))
commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, consHash, resHash, 0,
len(keys))
}
// initialize a certifier with the initial state
cert, _ := lite.NewInquiringCertifier(chainID, commits[0], trust, source)
// store a few commits as trust
for _, i := range []int{2, 5} {
trust.StoreCommit(commits[i])
}
// let's see if we can jump forward using trusted commits
err := source.StoreCommit(commits[7])
require.Nil(err, "%+v", err)
check := commits[7].Commit
err = cert.Certify(check)
require.Nil(err, "%+v", err)
assert.Equal(check.Height(), cert.LastHeight())
// add access to all commits via untrusted source
for i := 0; i < count; i++ {
err := source.StoreCommit(commits[i])
require.Nil(err)
}
// try to check an unknown seed in the past
mid := commits[3].Commit
err = cert.Certify(mid)
require.Nil(err, "%+v", err)
assert.Equal(mid.Height(), cert.LastHeight())
// and jump all the way forward again
end := commits[count-1].Commit
err = cert.Certify(end)
require.Nil(err, "%+v", err)
assert.Equal(end.Height(), cert.LastHeight())
}