From fd68bc7cfda1592114f574e2bd2101ae62acd255 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 3 Apr 2017 16:18:03 +0200 Subject: [PATCH] Test Tx proofs secure --- types/tx_test.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 types/tx_test.go diff --git a/types/tx_test.go b/types/tx_test.go new file mode 100644 index 000000000..2d4abc5b0 --- /dev/null +++ b/types/tx_test.go @@ -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) + } +}