|
@ -0,0 +1,105 @@ |
|
|
|
|
|
package types |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
|
"testing" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert" |
|
|
|
|
|
cmn "github.com/tendermint/go-common" |
|
|
|
|
|
ctest "github.com/tendermint/go-common/test" |
|
|
|
|
|
wire "github.com/tendermint/go-wire" |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
func makeTxs(cnt, size int) Txs { |
|
|
|
|
|
txs := make(Txs, cnt) |
|
|
|
|
|
for i := 0; i < cnt; i++ { |
|
|
|
|
|
txs[i] = cmn.RandBytes(size) |
|
|
|
|
|
} |
|
|
|
|
|
return txs |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func randInt(low, high int) int { |
|
|
|
|
|
off := cmn.RandInt() % (high - low) |
|
|
|
|
|
return low + off |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestValidTxProof(t *testing.T) { |
|
|
|
|
|
assert := assert.New(t) |
|
|
|
|
|
cases := []struct { |
|
|
|
|
|
txs Txs |
|
|
|
|
|
}{ |
|
|
|
|
|
{Txs{{1, 4, 34, 87, 163, 1}}}, |
|
|
|
|
|
{Txs{{5, 56, 165, 2}, {4, 77}}}, |
|
|
|
|
|
{Txs{Tx("foo"), Tx("bar"), Tx("baz")}}, |
|
|
|
|
|
{makeTxs(20, 5)}, |
|
|
|
|
|
{makeTxs(7, 81)}, |
|
|
|
|
|
{makeTxs(61, 15)}, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for h, tc := range cases { |
|
|
|
|
|
txs := tc.txs |
|
|
|
|
|
root := txs.Hash() |
|
|
|
|
|
// make sure valid proof for every tx
|
|
|
|
|
|
for i := range txs { |
|
|
|
|
|
leaf := txs[i] |
|
|
|
|
|
leafHash := leaf.Hash() |
|
|
|
|
|
proof := txs.Proof(i) |
|
|
|
|
|
assert.Equal(i, proof.Index, "%d: %d", h, i) |
|
|
|
|
|
assert.Equal(len(txs), proof.Total, "%d: %d", h, i) |
|
|
|
|
|
assert.Equal(root, proof.RootHash, "%d: %d", h, i) |
|
|
|
|
|
assert.Equal(leaf, proof.Data, "%d: %d", h, i) |
|
|
|
|
|
assert.Equal(leafHash, proof.LeafHash(), "%d: %d", h, i) |
|
|
|
|
|
assert.Nil(proof.Validate(root), "%d: %d", h, i) |
|
|
|
|
|
assert.NotNil(proof.Validate([]byte("foobar")), "%d: %d", h, i) |
|
|
|
|
|
|
|
|
|
|
|
// read-write must also work
|
|
|
|
|
|
var p2 TxProof |
|
|
|
|
|
bin := wire.BinaryBytes(proof) |
|
|
|
|
|
err := wire.ReadBinaryBytes(bin, &p2) |
|
|
|
|
|
if assert.Nil(err, "%d: %d: %+v", h, i, err) { |
|
|
|
|
|
assert.Nil(p2.Validate(root), "%d: %d", h, i) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestTxProofUnchangable(t *testing.T) { |
|
|
|
|
|
// run the other test a bunch...
|
|
|
|
|
|
for i := 0; i < 4; i++ { |
|
|
|
|
|
testTxProofUnchangable(t) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func testTxProofUnchangable(t *testing.T) { |
|
|
|
|
|
assert := assert.New(t) |
|
|
|
|
|
|
|
|
|
|
|
// make some proof
|
|
|
|
|
|
txs := makeTxs(randInt(2, 100), randInt(16, 128)) |
|
|
|
|
|
root := txs.Hash() |
|
|
|
|
|
i := randInt(0, len(txs)-1) |
|
|
|
|
|
proof := txs.Proof(i) |
|
|
|
|
|
|
|
|
|
|
|
// make sure it is valid to start with
|
|
|
|
|
|
assert.Nil(proof.Validate(root)) |
|
|
|
|
|
bin := wire.BinaryBytes(proof) |
|
|
|
|
|
|
|
|
|
|
|
// try mutating the data and make sure nothing breaks
|
|
|
|
|
|
for j := 0; j < 50; j++ { |
|
|
|
|
|
bad := ctest.MutateByteSlice(bin) |
|
|
|
|
|
assertBadProof(t, root, bad) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// this make sure the proof doesn't deserialize into something valid
|
|
|
|
|
|
func assertBadProof(t *testing.T, root []byte, bad []byte) { |
|
|
|
|
|
// we kind of expect this to panic sometimes... (bad, go-wire, bad)
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
recover() |
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
var proof TxProof |
|
|
|
|
|
err := wire.ReadBinaryBytes(bad, &proof) |
|
|
|
|
|
if err == nil { |
|
|
|
|
|
err = proof.Validate(root) |
|
|
|
|
|
assert.NotNil(t, err, "%+v", err) |
|
|
|
|
|
} |
|
|
|
|
|
} |