diff --git a/abci/types/types.go b/abci/types/types.go index 5f620b2d5..2fc1d62d0 100644 --- a/abci/types/types.go +++ b/abci/types/types.go @@ -264,11 +264,11 @@ func (rpp *ResponsePrepareProposal) Validate(maxSizeBytes int64, otxs [][]byte) if size > maxSizeBytes { return fmt.Errorf("transaction data size %d exceeds maximum %d", size, maxSizeBytes) } - if _, ok := ntx[string(tr.Tx)]; ok { - return errors.New("duplicate included transaction") - } - ntx[string(tr.Tx)] = struct{}{} } + if _, ok := ntx[string(tr.Tx)]; ok { + return errors.New("TxRecords contains duplicate transaction") + } + ntx[string(tr.Tx)] = struct{}{} if _, ok := otxsSet[string(tr.Tx)]; ok { if tr.Action == TxRecord_ADDED { return fmt.Errorf("unmodified transaction incorrectly marked as %s", tr.Action.String()) diff --git a/abci/types/types_test.go b/abci/types/types_test.go index be16a4145..6c2b04559 100644 --- a/abci/types/types_test.go +++ b/abci/types/types_test.go @@ -87,6 +87,31 @@ func TestValidateResponsePrepareProposal(t *testing.T) { err := rpp.Validate(100, [][]byte{}) require.Error(t, err) }) + t.Run("should error on duplicate transactions", func(t *testing.T) { + rpp := &abci.ResponsePrepareProposal{ + ModifiedTx: true, + TxRecords: []*abci.TxRecord{ + { + Action: abci.TxRecord_ADDED, + Tx: []byte{1, 2, 3, 4, 5}, + }, + { + Action: abci.TxRecord_ADDED, + Tx: []byte{100}, + }, + { + Action: abci.TxRecord_REMOVED, + Tx: []byte{1, 2, 3, 4, 5}, + }, + { + Action: abci.TxRecord_ADDED, + Tx: []byte{200}, + }, + }, + } + err := rpp.Validate(100, [][]byte{}) + require.Error(t, err) + }) t.Run("should error on new transactions marked UNMODIFIED", func(t *testing.T) { rpp := &abci.ResponsePrepareProposal{ ModifiedTx: true,