From ab114464c1eb046a6b6660ee10622991e08bc1af Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 5 Dec 2024 19:12:07 +0100 Subject: [PATCH 01/13] fix: cap tx size --- app/check_tx.go | 9 + app/test/check_tx_test.go | 25 +++ app/test/prepare_proposal_test.go | 223 +++++++++++--------- app/test/process_proposal_test.go | 4 +- app/validate_txs.go | 16 +- test/util/blobfactory/payforblob_factory.go | 3 +- 6 files changed, 172 insertions(+), 108 deletions(-) diff --git a/app/check_tx.go b/app/check_tx.go index f76b37880f..7b610e00c3 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -15,6 +15,15 @@ import ( // transactions that contain blobs. func (app *App) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { tx := req.Tx + + // all txs should be under the max tx size limit + maxTxSize := appconsts.MaxTxSize(app.AppVersion()) + currentTxSize := len(tx) + if currentTxSize > appconsts.MaxTxSize(app.AppVersion()) { + err := fmt.Errorf("tx size %d bytes is larger than the application's configured threshold of %d bytes", currentTxSize, maxTxSize) + return sdkerrors.ResponseCheckTxWithEvents(err, 0, 0, []abci.Event{}, false) + } + // check if the transaction contains blobs btx, isBlob, err := blobtx.UnmarshalBlobTx(tx) if isBlob && err != nil { diff --git a/app/test/check_tx_test.go b/app/test/check_tx_test.go index aba7720547..5918a0ca68 100644 --- a/app/test/check_tx_test.go +++ b/app/test/check_tx_test.go @@ -217,6 +217,31 @@ func TestCheckTx(t *testing.T) { }, expectedABCICode: abci.CodeTypeOK, }, + { + name: "v1 blob over 2MiB", + checkType: abci.CheckTxType_New, + getTx: func() []byte { + signer := createSigner(t, kr, accs[10], encCfg.TxConfig, 11) + blob, err := share.NewV1Blob(share.RandomBlobNamespace(), bytes.Repeat([]byte{1}, 2_000_000), signer.Account(accs[10]).Address()) + require.NoError(t, err) + blobTx, _, err := signer.CreatePayForBlobs(accs[10], []*share.Blob{blob}, opts...) + require.NoError(t, err) + return blobTx + }, + expectedABCICode: blobtypes.ErrBlobsTooLarge.ABCICode(), + }, + { + name: "v0 blob over 2MiB", + checkType: abci.CheckTxType_New, + getTx: func() []byte { + signer := createSigner(t, kr, accs[10], encCfg.TxConfig, 11) + blob, err := share.NewV0Blob(share.RandomBlobNamespace(), bytes.Repeat([]byte{1}, 2_000_000)) + require.NoError(t, err) + blobTx, _, err := signer.CreatePayForBlobs(accs[10], []*share.Blob{blob}, opts...) + require.NoError(t, err) + return blobTx + }, + }, } for _, tt := range tests { diff --git a/app/test/prepare_proposal_test.go b/app/test/prepare_proposal_test.go index f274d9da6a..b7d3ce2513 100644 --- a/app/test/prepare_proposal_test.go +++ b/app/test/prepare_proposal_test.go @@ -2,6 +2,7 @@ package app_test import ( "crypto/rand" + "fmt" "strings" "testing" "time" @@ -51,7 +52,6 @@ func TestPrepareProposalPutsPFBsAtEnd(t *testing.T) { accnts[:numBlobTxs], infos[:numBlobTxs], testfactory.Repeat([]*share.Blob{protoBlob}, numBlobTxs), - blobfactory.DefaultTxOpts()..., ) normalTxs := testutil.SendTxsWithAccounts( @@ -97,75 +97,74 @@ func TestPrepareProposalFiltering(t *testing.T) { // create 3 single blob blobTxs that are signed with valid account numbers // and sequences - blobTxs := blobfactory.ManyMultiBlobTx( - t, - encConf.TxConfig, - kr, - testutil.ChainID, - accounts[:3], - infos[:3], - blobfactory.NestedBlobs( - t, - testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - [][]int{{100}, {1000}, {420}}, - ), - blobfactory.DefaultTxOpts()..., - ) + // blobTxs := blobfactory.ManyMultiBlobTx( + // t, + // encConf.TxConfig, + // kr, + // testutil.ChainID, + // accounts[:3], + // infos[:3], + // blobfactory.NestedBlobs( + // t, + // testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), + // [][]int{{100}, {1000}, {420}}, + // ), + // ) // create 3 MsgSend transactions that are signed with valid account numbers // and sequences - sendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( - t, - testApp, - encConf.TxConfig, - kr, - 1000, - accounts[0], - accounts[len(accounts)-3:], - testutil.ChainID, - )).ToSliceOfBytes() - - validTxs := func() [][]byte { - txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)) - txs = append(txs, blobTxs...) - txs = append(txs, sendTxs...) - return txs - } + // sendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( + // t, + // testApp, + // encConf.TxConfig, + // kr, + // 1000, + // accounts[0], + // accounts[len(accounts)-3:], + // testutil.ChainID, + // )).ToSliceOfBytes() + + // validTxs := func() [][]byte { + // txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)) + // txs = append(txs, blobTxs...) + // txs = append(txs, sendTxs...) + // return txs + // } // create 3 MsgSend transactions that are using the same sequence as the // first three blob transactions above - duplicateSeqSendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( - t, - testApp, - encConf.TxConfig, - kr, - 1000, - accounts[0], - accounts[:3], - testutil.ChainID, - )).ToSliceOfBytes() + // duplicateSeqSendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( + // t, + // testApp, + // encConf.TxConfig, + // kr, + // 1000, + // accounts[0], + // accounts[:3], + // testutil.ChainID, + // )).ToSliceOfBytes() // create a transaction with an account that doesn't exist. This will cause the increment nonce nilAccount := "carmon san diego" _, _, err := kr.NewMnemonic(nilAccount, keyring.English, "", "", hd.Secp256k1) require.NoError(t, err) - noAccountTx := []byte(testutil.SendTxWithManualSequence(t, encConf.TxConfig, kr, nilAccount, accounts[0], 1000, "", 0, 6)) + // noAccountTx := []byte(testutil.SendTxWithManualSequence(t, encConf.TxConfig, kr, nilAccount, accounts[0], 1000, "", 0, 6)) // create a tx that can't be included in a 64 x 64 when accounting for the // pfb along with the shares - tooManyShareBtx := blobfactory.ManyMultiBlobTx( - t, - encConf.TxConfig, - kr, - testutil.ChainID, - accounts[3:4], - infos[3:4], - blobfactory.NestedBlobs( - t, - testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4000), - [][]int{repeat(4000, 1)}, - ), - )[0] + // tooManyShareBtx := blobfactory.ManyMultiBlobTx( + // t, + // encConf.TxConfig, + // kr, + // testutil.ChainID, + // accounts[3:4], + // infos[3:4], + // blobfactory.NestedBlobs( + // t, + // testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4000), + // [][]int{repeat(4000, 1)}, + // ), + // )[0] // memo is 2 MiB resulting in the transaction being over limit largeString := strings.Repeat("a", 2*1024*1024) @@ -184,11 +183,25 @@ func TestPrepareProposalFiltering(t *testing.T) { blobfactory.NestedBlobs( t, testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - [][]int{{100}, {1000}, {420}}, + [][]int{{699050}, {699050}, {699050}}, // over 2MiB, equal to 2 MiB, and under 2 MiB ), - user.SetMemo(largeString), ) + // 3 blobTxs where one is over MaxTxSize limit + // mixedSizeBlobTxs := blobfactory.ManyMultiBlobTx( + // t, + // encConf.TxConfig, + // kr, + // testutil.ChainID, + // accounts[:2], + // infos[:2], + // blobfactory.NestedBlobs( + // t, + // testfactory.RandomBlobNamespaces(tmrand.NewRand(), 2), + // [][]int{{2}, {2800}, {2097152}}, + // ), + // ) + type test struct { name string txs func() [][]byte @@ -196,50 +209,50 @@ func TestPrepareProposalFiltering(t *testing.T) { } tests := []test{ - { - name: "all valid txs, none are pruned", - txs: func() [][]byte { return validTxs() }, - prunedTxs: [][]byte{}, - }, - { - // even though duplicateSeqSendTxs are getting appended to the end of the - // block, and we do not check the signatures of the standard txs, - // the blob txs still get pruned because we are separating the - // normal and blob txs, and checking/executing the normal txs first. - name: "duplicate sequence appended to the end of the block", - txs: func() [][]byte { - return append(validTxs(), duplicateSeqSendTxs...) - }, - prunedTxs: blobTxs, - }, - { - name: "duplicate sequence txs", - txs: func() [][]byte { - txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)+len(duplicateSeqSendTxs)) - // these should increment the nonce of the accounts that are - // signing the blobtxs, which should make those signatures - // invalid. - txs = append(txs, duplicateSeqSendTxs...) - txs = append(txs, blobTxs...) - txs = append(txs, sendTxs...) - return txs - }, - prunedTxs: blobTxs, - }, - { - name: "nil account panic catch", - txs: func() [][]byte { - return [][]byte{noAccountTx} - }, - prunedTxs: [][]byte{noAccountTx}, - }, - { - name: "blob tx with too many shares", - txs: func() [][]byte { - return [][]byte{tooManyShareBtx} - }, - prunedTxs: [][]byte{tooManyShareBtx}, - }, + // { + // name: "all valid txs, none are pruned", + // txs: func() [][]byte { return validTxs() }, + // prunedTxs: [][]byte{}, + // }, + // { + // // even though duplicateSeqSendTxs are getting appended to the end of the + // // block, and we do not check the signatures of the standard txs, + // // the blob txs still get pruned because we are separating the + // // normal and blob txs, and checking/executing the normal txs first. + // name: "duplicate sequence appended to the end of the block", + // txs: func() [][]byte { + // return append(validTxs(), duplicateSeqSendTxs...) + // }, + // prunedTxs: blobTxs, + // }, + // { + // name: "duplicate sequence txs", + // txs: func() [][]byte { + // txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)+len(duplicateSeqSendTxs)) + // // these should increment the nonce of the accounts that are + // // signing the blobtxs, which should make those signatures + // // invalid. + // txs = append(txs, duplicateSeqSendTxs...) + // txs = append(txs, blobTxs...) + // txs = append(txs, sendTxs...) + // return txs + // }, + // prunedTxs: blobTxs, + // }, + // { + // name: "nil account panic catch", + // txs: func() [][]byte { + // return [][]byte{noAccountTx} + // }, + // prunedTxs: [][]byte{noAccountTx}, + // }, + // { + // name: "blob tx with too many shares", + // txs: func() [][]byte { + // return [][]byte{tooManyShareBtx} + // }, + // prunedTxs: [][]byte{tooManyShareBtx}, + // }, { name: "blobTxs and sendTxs that exceed MaxTxSize limit", txs: func() [][]byte { @@ -260,10 +273,16 @@ func TestPrepareProposalFiltering(t *testing.T) { Height: height, Time: blockTime, }) + fmt.Println( + "EXPECTED TXS", len(tt.txs())-len(tt.prunedTxs), + "RESPONSE TXS", len(resp.BlockData.Txs), + ) // check that we have the expected number of transactions require.Equal(t, len(tt.txs())-len(tt.prunedTxs), len(resp.BlockData.Txs)) // check that the expected txs were removed for _, ptx := range tt.prunedTxs { + fmt.Println("PTX: ", len(ptx)) + fmt.Println(len(tt.prunedTxs), "PRUNED TXS") require.NotContains(t, resp.BlockData.Txs, ptx) } }) diff --git a/app/test/process_proposal_test.go b/app/test/process_proposal_test.go index 33b1d406c5..34e79c8fe2 100644 --- a/app/test/process_proposal_test.go +++ b/app/test/process_proposal_test.go @@ -51,7 +51,6 @@ func TestProcessProposal(t *testing.T) { testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4), [][]int{{100}, {1000}, {420}, {300}}, ), - blobfactory.DefaultTxOpts()..., ) largeMemo := strings.Repeat("a", appconsts.MaxTxSize(appconsts.LatestVersion)) @@ -64,8 +63,7 @@ func TestProcessProposal(t *testing.T) { t, testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4), [][]int{{100}, {1000}, {420}, {300}}, - ), - user.SetMemo(largeMemo)) + )) // create 1 large sendTx that includes a large memo making the // transaction over the configured max tx size limit diff --git a/app/validate_txs.go b/app/validate_txs.go index ee3edfbb6f..90ff84dfbc 100644 --- a/app/validate_txs.go +++ b/app/validate_txs.go @@ -1,6 +1,8 @@ package app import ( + "fmt" + "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" "github.com/celestiaorg/go-square/v2/tx" "github.com/cosmos/cosmos-sdk/client" @@ -34,7 +36,19 @@ func separateTxs(_ client.TxConfig, rawTxs [][]byte) ([][]byte, []*tx.BlobTx) { // // Side-effect: arranges all normal transactions before all blob transactions. func FilterTxs(logger log.Logger, ctx sdk.Context, handler sdk.AnteHandler, txConfig client.TxConfig, txs [][]byte) [][]byte { - normalTxs, blobTxs := separateTxs(txConfig, txs) + // all transactions should be below the max tx size + maxTxSize := appconsts.MaxTxSize(ctx.BlockHeader().Version.App) + var txsBelowLimit [][]byte + for _, tx := range txs { + if len(tx) > maxTxSize { + err := fmt.Sprintf("tx size %d bytes is larger than the application's configured threshold of %d bytes", len(tx), maxTxSize) + logger.Error(err) + continue + } + txsBelowLimit = append(txsBelowLimit, tx) + } + + normalTxs, blobTxs := separateTxs(txConfig, txsBelowLimit) normalTxs, ctx = filterStdTxs(logger, txConfig.TxDecoder(), ctx, handler, normalTxs) blobTxs, _ = filterBlobTxs(logger, txConfig.TxDecoder(), ctx, handler, blobTxs) return append(normalTxs, encodeBlobTxs(blobTxs)...) diff --git a/test/util/blobfactory/payforblob_factory.go b/test/util/blobfactory/payforblob_factory.go index f9b05359bc..d15e7ca0fe 100644 --- a/test/util/blobfactory/payforblob_factory.go +++ b/test/util/blobfactory/payforblob_factory.go @@ -245,14 +245,13 @@ func ManyMultiBlobTx( accounts []string, accInfos []AccountInfo, blobs [][]*share.Blob, - opts ...user.TxOption, ) [][]byte { t.Helper() txs := make([][]byte, len(accounts)) for i, acc := range accounts { signer, err := user.NewSigner(kr, enc, chainid, appconsts.LatestVersion, user.NewAccount(acc, accInfos[i].AccountNum, accInfos[i].Sequence)) require.NoError(t, err) - txs[i], _, err = signer.CreatePayForBlobs(acc, blobs[i], opts...) + txs[i], _, err = signer.CreatePayForBlobs(acc, blobs[i], DefaultTxOpts()...) require.NoError(t, err) } return txs From 19b5053d1cdbe8b41209fddc4fabf40cbd9aee12 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 6 Dec 2024 12:38:55 +0100 Subject: [PATCH 02/13] test: prepare proposal filters blobs over limit --- app/test/prepare_proposal_test.go | 238 +++++++++++++++--------------- 1 file changed, 120 insertions(+), 118 deletions(-) diff --git a/app/test/prepare_proposal_test.go b/app/test/prepare_proposal_test.go index b7d3ce2513..9ff9470aed 100644 --- a/app/test/prepare_proposal_test.go +++ b/app/test/prepare_proposal_test.go @@ -97,74 +97,74 @@ func TestPrepareProposalFiltering(t *testing.T) { // create 3 single blob blobTxs that are signed with valid account numbers // and sequences - // blobTxs := blobfactory.ManyMultiBlobTx( - // t, - // encConf.TxConfig, - // kr, - // testutil.ChainID, - // accounts[:3], - // infos[:3], - // blobfactory.NestedBlobs( - // t, - // testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - // [][]int{{100}, {1000}, {420}}, - // ), - // ) + blobTxs := blobfactory.ManyMultiBlobTx( + t, + encConf.TxConfig, + kr, + testutil.ChainID, + accounts[:3], + infos[:3], + blobfactory.NestedBlobs( + t, + testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), + [][]int{{100}, {1000}, {420}}, + ), + ) // create 3 MsgSend transactions that are signed with valid account numbers // and sequences - // sendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( - // t, - // testApp, - // encConf.TxConfig, - // kr, - // 1000, - // accounts[0], - // accounts[len(accounts)-3:], - // testutil.ChainID, - // )).ToSliceOfBytes() - - // validTxs := func() [][]byte { - // txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)) - // txs = append(txs, blobTxs...) - // txs = append(txs, sendTxs...) - // return txs - // } + sendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( + t, + testApp, + encConf.TxConfig, + kr, + 1000, + accounts[0], + accounts[len(accounts)-3:], + testutil.ChainID, + )).ToSliceOfBytes() + + validTxs := func() [][]byte { + txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)) + txs = append(txs, blobTxs...) + txs = append(txs, sendTxs...) + return txs + } // create 3 MsgSend transactions that are using the same sequence as the // first three blob transactions above - // duplicateSeqSendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( - // t, - // testApp, - // encConf.TxConfig, - // kr, - // 1000, - // accounts[0], - // accounts[:3], - // testutil.ChainID, - // )).ToSliceOfBytes() + duplicateSeqSendTxs := coretypes.Txs(testutil.SendTxsWithAccounts( + t, + testApp, + encConf.TxConfig, + kr, + 1000, + accounts[0], + accounts[:3], + testutil.ChainID, + )).ToSliceOfBytes() // create a transaction with an account that doesn't exist. This will cause the increment nonce nilAccount := "carmon san diego" _, _, err := kr.NewMnemonic(nilAccount, keyring.English, "", "", hd.Secp256k1) require.NoError(t, err) - // noAccountTx := []byte(testutil.SendTxWithManualSequence(t, encConf.TxConfig, kr, nilAccount, accounts[0], 1000, "", 0, 6)) + noAccountTx := []byte(testutil.SendTxWithManualSequence(t, encConf.TxConfig, kr, nilAccount, accounts[0], 1000, "", 0, 6)) // create a tx that can't be included in a 64 x 64 when accounting for the // pfb along with the shares - // tooManyShareBtx := blobfactory.ManyMultiBlobTx( - // t, - // encConf.TxConfig, - // kr, - // testutil.ChainID, - // accounts[3:4], - // infos[3:4], - // blobfactory.NestedBlobs( - // t, - // testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4000), - // [][]int{repeat(4000, 1)}, - // ), - // )[0] + tooManyShareBtx := blobfactory.ManyMultiBlobTx( + t, + encConf.TxConfig, + kr, + testutil.ChainID, + accounts[3:4], + infos[3:4], + blobfactory.NestedBlobs( + t, + testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4000), + [][]int{repeat(4000, 1)}, + ), + )[0] // memo is 2 MiB resulting in the transaction being over limit largeString := strings.Repeat("a", 2*1024*1024) @@ -172,6 +172,7 @@ func TestPrepareProposalFiltering(t *testing.T) { // 3 transactions over MaxTxSize limit largeTxs := coretypes.Txs(testutil.SendTxsWithAccounts(t, testApp, encConf.TxConfig, kr, 1000, accounts[0], accounts[:3], testutil.ChainID, user.SetMemo(largeString))).ToSliceOfBytes() + maxTxSize := appconsts.MaxTxSize(testApp.AppVersion()) // max tx size for the latest version // 3 blobTxs over MaxTxSize limit largeBlobTxs := blobfactory.ManyMultiBlobTx( t, @@ -183,24 +184,24 @@ func TestPrepareProposalFiltering(t *testing.T) { blobfactory.NestedBlobs( t, testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - [][]int{{699050}, {699050}, {699050}}, // over 2MiB, equal to 2 MiB, and under 2 MiB + [][]int{{maxTxSize + 1}, {maxTxSize + 1}, {maxTxSize + 1}}, // over 2MiB, equal to 2 MiB, and under 2 MiB ), ) // 3 blobTxs where one is over MaxTxSize limit - // mixedSizeBlobTxs := blobfactory.ManyMultiBlobTx( - // t, - // encConf.TxConfig, - // kr, - // testutil.ChainID, - // accounts[:2], - // infos[:2], - // blobfactory.NestedBlobs( - // t, - // testfactory.RandomBlobNamespaces(tmrand.NewRand(), 2), - // [][]int{{2}, {2800}, {2097152}}, - // ), - // ) + mixedSizeBlobTxs := blobfactory.ManyMultiBlobTx( + t, + encConf.TxConfig, + kr, + testutil.ChainID, + accounts[:3], + infos[:3], + blobfactory.NestedBlobs( + t, + testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), + [][]int{{2}, {2800}, {maxTxSize + 1}}, + ), + ) type test struct { name string @@ -209,50 +210,50 @@ func TestPrepareProposalFiltering(t *testing.T) { } tests := []test{ - // { - // name: "all valid txs, none are pruned", - // txs: func() [][]byte { return validTxs() }, - // prunedTxs: [][]byte{}, - // }, - // { - // // even though duplicateSeqSendTxs are getting appended to the end of the - // // block, and we do not check the signatures of the standard txs, - // // the blob txs still get pruned because we are separating the - // // normal and blob txs, and checking/executing the normal txs first. - // name: "duplicate sequence appended to the end of the block", - // txs: func() [][]byte { - // return append(validTxs(), duplicateSeqSendTxs...) - // }, - // prunedTxs: blobTxs, - // }, - // { - // name: "duplicate sequence txs", - // txs: func() [][]byte { - // txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)+len(duplicateSeqSendTxs)) - // // these should increment the nonce of the accounts that are - // // signing the blobtxs, which should make those signatures - // // invalid. - // txs = append(txs, duplicateSeqSendTxs...) - // txs = append(txs, blobTxs...) - // txs = append(txs, sendTxs...) - // return txs - // }, - // prunedTxs: blobTxs, - // }, - // { - // name: "nil account panic catch", - // txs: func() [][]byte { - // return [][]byte{noAccountTx} - // }, - // prunedTxs: [][]byte{noAccountTx}, - // }, - // { - // name: "blob tx with too many shares", - // txs: func() [][]byte { - // return [][]byte{tooManyShareBtx} - // }, - // prunedTxs: [][]byte{tooManyShareBtx}, - // }, + { + name: "all valid txs, none are pruned", + txs: func() [][]byte { return validTxs() }, + prunedTxs: [][]byte{}, + }, + { + // even though duplicateSeqSendTxs are getting appended to the end of the + // block, and we do not check the signatures of the standard txs, + // the blob txs still get pruned because we are separating the + // normal and blob txs, and checking/executing the normal txs first. + name: "duplicate sequence appended to the end of the block", + txs: func() [][]byte { + return append(validTxs(), duplicateSeqSendTxs...) + }, + prunedTxs: blobTxs, + }, + { + name: "duplicate sequence txs", + txs: func() [][]byte { + txs := make([][]byte, 0, len(sendTxs)+len(blobTxs)+len(duplicateSeqSendTxs)) + // these should increment the nonce of the accounts that are + // signing the blobtxs, which should make those signatures + // invalid. + txs = append(txs, duplicateSeqSendTxs...) + txs = append(txs, blobTxs...) + txs = append(txs, sendTxs...) + return txs + }, + prunedTxs: blobTxs, + }, + { + name: "nil account panic catch", + txs: func() [][]byte { + return [][]byte{noAccountTx} + }, + prunedTxs: [][]byte{noAccountTx}, + }, + { + name: "blob tx with too many shares", + txs: func() [][]byte { + return [][]byte{tooManyShareBtx} + }, + prunedTxs: [][]byte{tooManyShareBtx}, + }, { name: "blobTxs and sendTxs that exceed MaxTxSize limit", txs: func() [][]byte { @@ -260,6 +261,13 @@ func TestPrepareProposalFiltering(t *testing.T) { }, prunedTxs: append(largeTxs, largeBlobTxs...), }, + { + name: "blobTxs with mixed sizes, one is over MaxTxSize limit", + txs: func() [][]byte { + return mixedSizeBlobTxs + }, + prunedTxs: [][]byte{mixedSizeBlobTxs[2]}, + }, } for _, tt := range tests { @@ -273,16 +281,10 @@ func TestPrepareProposalFiltering(t *testing.T) { Height: height, Time: blockTime, }) - fmt.Println( - "EXPECTED TXS", len(tt.txs())-len(tt.prunedTxs), - "RESPONSE TXS", len(resp.BlockData.Txs), - ) // check that we have the expected number of transactions require.Equal(t, len(tt.txs())-len(tt.prunedTxs), len(resp.BlockData.Txs)) // check that the expected txs were removed for _, ptx := range tt.prunedTxs { - fmt.Println("PTX: ", len(ptx)) - fmt.Println(len(tt.prunedTxs), "PRUNED TXS") require.NotContains(t, resp.BlockData.Txs, ptx) } }) From 9cad25d0df48f282316ab75983ac4df9631f02e4 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 6 Dec 2024 14:14:43 +0100 Subject: [PATCH 03/13] test: works for check tx --- app/test/check_tx_test.go | 27 +++++++++++++++++---------- app/test/prepare_proposal_test.go | 1 - app/validate_txs.go | 4 ++-- test/util/blobfactory/test_util.go | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/app/test/check_tx_test.go b/app/test/check_tx_test.go index 5918a0ca68..bd894bbe23 100644 --- a/app/test/check_tx_test.go +++ b/app/test/check_tx_test.go @@ -32,7 +32,9 @@ func TestCheckTx(t *testing.T) { ns1, err := share.NewV0Namespace(bytes.Repeat([]byte{1}, share.NamespaceVersionZeroIDSize)) require.NoError(t, err) - accs := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"} + var genericErrorCode uint32 = 1 + + accs := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"} testApp, kr := testutil.SetupTestAppWithGenesisValSet(app.DefaultConsensusParams(), accs...) testApp.Commit() @@ -44,6 +46,7 @@ func TestCheckTx(t *testing.T) { checkType abci.CheckTxType getTx func() []byte expectedABCICode uint32 + expectedLog string } tests := []test{ @@ -173,11 +176,11 @@ func TestCheckTx(t *testing.T) { expectedABCICode: abci.CodeTypeOK, }, { - name: "10,000,000 byte blob", + name: "2,000,000 byte blob", checkType: abci.CheckTxType_New, getTx: func() []byte { signer := createSigner(t, kr, accs[9], encCfg.TxConfig, 10) - _, blobs := blobfactory.RandMsgPayForBlobsWithSigner(tmrand.NewRand(), signer.Account(accs[9]).Address().String(), 10_000_000, 1) + _, blobs := blobfactory.RandMsgPayForBlobsWithSigner(tmrand.NewRand(), signer.Account(accs[9]).Address().String(), 2_000_000, 1) tx, _, err := signer.CreatePayForBlobs(accs[9], blobs, opts...) require.NoError(t, err) return tx @@ -221,26 +224,29 @@ func TestCheckTx(t *testing.T) { name: "v1 blob over 2MiB", checkType: abci.CheckTxType_New, getTx: func() []byte { - signer := createSigner(t, kr, accs[10], encCfg.TxConfig, 11) - blob, err := share.NewV1Blob(share.RandomBlobNamespace(), bytes.Repeat([]byte{1}, 2_000_000), signer.Account(accs[10]).Address()) + signer := createSigner(t, kr, accs[11], encCfg.TxConfig, 12) + blob, err := share.NewV1Blob(share.RandomBlobNamespace(), bytes.Repeat([]byte{1}, 2097152), signer.Account(accs[11]).Address()) require.NoError(t, err) - blobTx, _, err := signer.CreatePayForBlobs(accs[10], []*share.Blob{blob}, opts...) + blobTx, _, err := signer.CreatePayForBlobs(accs[11], []*share.Blob{blob}, opts...) require.NoError(t, err) return blobTx }, - expectedABCICode: blobtypes.ErrBlobsTooLarge.ABCICode(), + expectedLog: "is larger than the application's configured threshold", + expectedABCICode: genericErrorCode, }, { name: "v0 blob over 2MiB", checkType: abci.CheckTxType_New, getTx: func() []byte { - signer := createSigner(t, kr, accs[10], encCfg.TxConfig, 11) - blob, err := share.NewV0Blob(share.RandomBlobNamespace(), bytes.Repeat([]byte{1}, 2_000_000)) + signer := createSigner(t, kr, accs[12], encCfg.TxConfig, 13) + blob, err := share.NewV0Blob(share.RandomBlobNamespace(), bytes.Repeat([]byte{1}, 2097152)) require.NoError(t, err) - blobTx, _, err := signer.CreatePayForBlobs(accs[10], []*share.Blob{blob}, opts...) + blobTx, _, err := signer.CreatePayForBlobs(accs[12], []*share.Blob{blob}, opts...) require.NoError(t, err) return blobTx }, + expectedLog: "is larger than the application's configured threshold", + expectedABCICode: genericErrorCode, }, } @@ -248,6 +254,7 @@ func TestCheckTx(t *testing.T) { t.Run(tt.name, func(t *testing.T) { resp := testApp.CheckTx(abci.RequestCheckTx{Type: tt.checkType, Tx: tt.getTx()}) assert.Equal(t, tt.expectedABCICode, resp.Code, resp.Log) + assert.Contains(t, resp.Log, tt.expectedLog) }) } } diff --git a/app/test/prepare_proposal_test.go b/app/test/prepare_proposal_test.go index 9ff9470aed..9ff1f0cea6 100644 --- a/app/test/prepare_proposal_test.go +++ b/app/test/prepare_proposal_test.go @@ -2,7 +2,6 @@ package app_test import ( "crypto/rand" - "fmt" "strings" "testing" "time" diff --git a/app/validate_txs.go b/app/validate_txs.go index 90ff84dfbc..9657dc8377 100644 --- a/app/validate_txs.go +++ b/app/validate_txs.go @@ -39,9 +39,9 @@ func FilterTxs(logger log.Logger, ctx sdk.Context, handler sdk.AnteHandler, txCo // all transactions should be below the max tx size maxTxSize := appconsts.MaxTxSize(ctx.BlockHeader().Version.App) var txsBelowLimit [][]byte - for _, tx := range txs { + for idx, tx := range txs { if len(tx) > maxTxSize { - err := fmt.Sprintf("tx size %d bytes is larger than the application's configured threshold of %d bytes", len(tx), maxTxSize) + err := fmt.Sprintf("tx size %d bytes at index %d exceeds the application's configured threshold of %d bytes", len(tx), idx, maxTxSize) logger.Error(err) continue } diff --git a/test/util/blobfactory/test_util.go b/test/util/blobfactory/test_util.go index 0496ba1735..90a0697d1b 100644 --- a/test/util/blobfactory/test_util.go +++ b/test/util/blobfactory/test_util.go @@ -11,7 +11,7 @@ import ( ) func DefaultTxOpts() []user.TxOption { - return FeeTxOpts(10_000_000) + return FeeTxOpts(10_000_000_000) } func FeeTxOpts(gas uint64) []user.TxOption { From bcbfc60046440ab118eefa08eb8609495dc9b05e Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 6 Dec 2024 14:38:00 +0100 Subject: [PATCH 04/13] fix: consistent apphash test --- app/test/consistent_apphash_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/test/consistent_apphash_test.go b/app/test/consistent_apphash_test.go index 9a108e4dd1..2acc1030ae 100644 --- a/app/test/consistent_apphash_test.go +++ b/app/test/consistent_apphash_test.go @@ -62,6 +62,10 @@ type appHashTest struct { expectedAppHash []byte } +func DefaultTxOpts() []user.TxOption { + return blobfactory.FeeTxOpts(10_000_000) +} + // TestConsistentAppHash executes all state machine messages on all app versions, generates an app hash, // and compares it against a previously generated hash from the same set of transactions. // App hashes across different commits should be consistent. @@ -377,7 +381,7 @@ func createEncodedBlobTx(t *testing.T, signer *user.Signer, accountAddresses []s blobTx := blobTx{ author: senderAcc.Name(), blobs: []*share.Blob{blob}, - txOptions: blobfactory.DefaultTxOpts(), + txOptions: DefaultTxOpts(), } encodedBlobTx, _, err := signer.CreatePayForBlobs(blobTx.author, blobTx.blobs, blobTx.txOptions...) require.NoError(t, err) @@ -429,7 +433,7 @@ func deterministicKeyRing(cdc codec.Codec) (keyring.Keyring, []types.PubKey) { func processSdkMessages(signer *user.Signer, sdkMessages []sdk.Msg) ([][]byte, error) { encodedTxs := make([][]byte, 0, len(sdkMessages)) for _, msg := range sdkMessages { - encodedTx, err := signer.CreateTx([]sdk.Msg{msg}, blobfactory.DefaultTxOpts()...) + encodedTx, err := signer.CreateTx([]sdk.Msg{msg}, DefaultTxOpts()...) if err != nil { return nil, err } From 4350f35f4fc095f3ab8a86503006b0204b21a20d Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 6 Dec 2024 14:44:17 +0100 Subject: [PATCH 05/13] test: remove tests for the logic that doesnt get hit --- app/test/process_proposal_test.go | 39 ------------------------------- 1 file changed, 39 deletions(-) diff --git a/app/test/process_proposal_test.go b/app/test/process_proposal_test.go index 34e79c8fe2..093116a85b 100644 --- a/app/test/process_proposal_test.go +++ b/app/test/process_proposal_test.go @@ -3,7 +3,6 @@ package app_test import ( "bytes" "fmt" - "strings" "testing" "time" @@ -53,24 +52,6 @@ func TestProcessProposal(t *testing.T) { ), ) - largeMemo := strings.Repeat("a", appconsts.MaxTxSize(appconsts.LatestVersion)) - - // create 2 single blobTxs that include a large memo making the transaction - // larger than the configured max tx size - largeBlobTxs := blobfactory.ManyMultiBlobTx( - t, enc, kr, testutil.ChainID, accounts[3:], infos[3:], - blobfactory.NestedBlobs( - t, - testfactory.RandomBlobNamespaces(tmrand.NewRand(), 4), - [][]int{{100}, {1000}, {420}, {300}}, - )) - - // create 1 large sendTx that includes a large memo making the - // transaction over the configured max tx size limit - largeSendTx := testutil.SendTxsWithAccounts( - t, testApp, enc, kr, 1000, accounts[0], accounts[1:2], testutil.ChainID, user.SetMemo(largeMemo), - ) - // create 3 MsgSend transactions that are signed with valid account numbers // and sequences sendTxs := testutil.SendTxsWithAccounts( @@ -347,26 +328,6 @@ func TestProcessProposal(t *testing.T) { appVersion: v3.Version, expectedResult: abci.ResponseProcessProposal_REJECT, }, - { - name: "blob txs larger than configured max tx size", - input: validData(), - mutator: func(d *tmproto.Data) { - d.Txs = append(d.Txs, largeBlobTxs...) - d.Hash = calculateNewDataHash(t, d.Txs) - }, - appVersion: appconsts.LatestVersion, - expectedResult: abci.ResponseProcessProposal_REJECT, - }, - { - name: "send tx larger than configured max tx size", - input: validData(), - mutator: func(d *tmproto.Data) { - d.Txs = append(coretypes.Txs(largeSendTx).ToSliceOfBytes(), d.Txs...) - d.Hash = calculateNewDataHash(t, d.Txs) - }, - appVersion: appconsts.LatestVersion, - expectedResult: abci.ResponseProcessProposal_REJECT, - }, } for _, tt := range tests { From 4943be334930257d3c0171eca3fd074f5153c7db Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 6 Dec 2024 15:12:45 +0100 Subject: [PATCH 06/13] test: fix big blobs test --- app/test/big_blob_test.go | 4 ++-- app/validate_txs.go | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/test/big_blob_test.go b/app/test/big_blob_test.go index cede1ae65d..f6c62e8441 100644 --- a/app/test/big_blob_test.go +++ b/app/test/big_blob_test.go @@ -67,8 +67,8 @@ func (s *BigBlobSuite) TestErrBlobsTooLarge() { } testCases := []testCase{ { - name: "2 mebibyte blob", - blob: newBlobWithSize(2 * mebibyte), + name: "~ 1.9 mebibyte blob", + blob: newBlobWithSize(2_000_000), want: blobtypes.ErrBlobsTooLarge.ABCICode(), }, } diff --git a/app/validate_txs.go b/app/validate_txs.go index 9657dc8377..346bcd7f45 100644 --- a/app/validate_txs.go +++ b/app/validate_txs.go @@ -38,6 +38,7 @@ func separateTxs(_ client.TxConfig, rawTxs [][]byte) ([][]byte, []*tx.BlobTx) { func FilterTxs(logger log.Logger, ctx sdk.Context, handler sdk.AnteHandler, txConfig client.TxConfig, txs [][]byte) [][]byte { // all transactions should be below the max tx size maxTxSize := appconsts.MaxTxSize(ctx.BlockHeader().Version.App) + //nolint:prealloc var txsBelowLimit [][]byte for idx, tx := range txs { if len(tx) > maxTxSize { From c4fc1f6261c22551200e018910e27ab13b99983f Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 6 Dec 2024 15:36:11 +0100 Subject: [PATCH 07/13] chore: remove irrelevant comment --- app/test/prepare_proposal_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/test/prepare_proposal_test.go b/app/test/prepare_proposal_test.go index 9ff1f0cea6..aca70fb7d3 100644 --- a/app/test/prepare_proposal_test.go +++ b/app/test/prepare_proposal_test.go @@ -183,7 +183,7 @@ func TestPrepareProposalFiltering(t *testing.T) { blobfactory.NestedBlobs( t, testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - [][]int{{maxTxSize + 1}, {maxTxSize + 1}, {maxTxSize + 1}}, // over 2MiB, equal to 2 MiB, and under 2 MiB + [][]int{{maxTxSize + 1}, {maxTxSize + 1}, {maxTxSize + 1}}, ), ) From aa314e9a635ab0ccf0ea160e2d6eb25bee78d0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Mon, 9 Dec 2024 09:30:24 +0100 Subject: [PATCH 08/13] Update app/check_tx.go Co-authored-by: Rootul P --- app/check_tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/check_tx.go b/app/check_tx.go index 7b610e00c3..3e5e2e1dd9 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -16,7 +16,7 @@ import ( func (app *App) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { tx := req.Tx - // all txs should be under the max tx size limit + // all txs must be less than or equal to the max tx size limit maxTxSize := appconsts.MaxTxSize(app.AppVersion()) currentTxSize := len(tx) if currentTxSize > appconsts.MaxTxSize(app.AppVersion()) { From 951e78bc37a262525429fc9287b710606d839bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Mon, 9 Dec 2024 09:38:00 +0100 Subject: [PATCH 09/13] Update app/check_tx.go Co-authored-by: Rootul P --- app/check_tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/check_tx.go b/app/check_tx.go index 3e5e2e1dd9..8bdf10cbad 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -19,7 +19,7 @@ func (app *App) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { // all txs must be less than or equal to the max tx size limit maxTxSize := appconsts.MaxTxSize(app.AppVersion()) currentTxSize := len(tx) - if currentTxSize > appconsts.MaxTxSize(app.AppVersion()) { + if currentTxSize > maxTxSize { err := fmt.Errorf("tx size %d bytes is larger than the application's configured threshold of %d bytes", currentTxSize, maxTxSize) return sdkerrors.ResponseCheckTxWithEvents(err, 0, 0, []abci.Event{}, false) } From 826f56b8bcfa13dfcc2ec31678e7a4b87ee61eec Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 9 Dec 2024 16:05:42 +0100 Subject: [PATCH 10/13] refactor: address comments --- app/check_tx.go | 5 +++-- app/errors/errors.go | 12 ++++++++++++ app/test/big_blob_test.go | 41 +++++++++++++++++++++++++++++++++++++-- app/test/check_tx_test.go | 15 ++++++++------ 4 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 app/errors/errors.go diff --git a/app/check_tx.go b/app/check_tx.go index 8bdf10cbad..e4adf62d2b 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -1,8 +1,10 @@ package app import ( + "cosmossdk.io/errors" "fmt" + apperr "github.com/celestiaorg/celestia-app/v3/app/errors" "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types" blobtx "github.com/celestiaorg/go-square/v2/tx" @@ -20,8 +22,7 @@ func (app *App) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { maxTxSize := appconsts.MaxTxSize(app.AppVersion()) currentTxSize := len(tx) if currentTxSize > maxTxSize { - err := fmt.Errorf("tx size %d bytes is larger than the application's configured threshold of %d bytes", currentTxSize, maxTxSize) - return sdkerrors.ResponseCheckTxWithEvents(err, 0, 0, []abci.Event{}, false) + return sdkerrors.ResponseCheckTxWithEvents(errors.Wrapf(apperr.ErrTxExceedsMaxSize, "tx size %d bytes is larger than the application's configured threshold of %d bytes", currentTxSize, maxTxSize), 0, 0, []abci.Event{}, false) } // check if the transaction contains blobs diff --git a/app/errors/errors.go b/app/errors/errors.go new file mode 100644 index 0000000000..9bbff18b42 --- /dev/null +++ b/app/errors/errors.go @@ -0,0 +1,12 @@ +package errors + +import ( + "cosmossdk.io/errors" +) + +const AppErrorsCodespace = "app" + +// general application errors +var ( + ErrTxExceedsMaxSize = errors.Register(AppErrorsCodespace, 11142, "exceeds max tx size limit") +) diff --git a/app/test/big_blob_test.go b/app/test/big_blob_test.go index f6c62e8441..1892453b17 100644 --- a/app/test/big_blob_test.go +++ b/app/test/big_blob_test.go @@ -15,6 +15,7 @@ import ( "github.com/celestiaorg/go-square/v2/share" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + apperrors "github.com/celestiaorg/celestia-app/v3/app/errors" ) func TestBigBlobSuite(t *testing.T) { @@ -55,7 +56,7 @@ func (s *BigBlobSuite) SetupSuite() { require.NoError(t, cctx.WaitForNextBlock()) } -// TestErrBlobsTooLarge verifies that submitting a 2 MiB blob hits ErrBlobsTooLarge. +// TestErrBlobsTooLarge verifies that submitting a ~1.9 MiB blob hits ErrBlobsTooLarge. func (s *BigBlobSuite) TestErrBlobsTooLarge() { t := s.T() @@ -67,7 +68,7 @@ func (s *BigBlobSuite) TestErrBlobsTooLarge() { } testCases := []testCase{ { - name: "~ 1.9 mebibyte blob", + name: "~ 1.9 MiB blob", blob: newBlobWithSize(2_000_000), want: blobtypes.ErrBlobsTooLarge.ABCICode(), }, @@ -88,3 +89,39 @@ func (s *BigBlobSuite) TestErrBlobsTooLarge() { }) } } + +// TestBlobExceedsMaxTxSize verifies that submitting a 2 MiB blob hits ErrTxExceedsMaxSize. +func (s *BigBlobSuite) TestBlobExceedsMaxTxSize() { + t := s.T() + + type testCase struct { + name string + blob *share.Blob + expectedCode uint32 + expectedErr string + } + testCases := []testCase{ + { + name: "2 MiB blob", + blob: newBlobWithSize(2097152), + expectedCode: apperrors.ErrTxExceedsMaxSize.ABCICode(), + expectedErr: apperrors.ErrTxExceedsMaxSize.Error(), + }, + } + + txClient, err := testnode.NewTxClientFromContext(s.cctx) + require.NoError(t, err) + + for _, tc := range testCases { + s.Run(tc.name, func() { + subCtx, cancel := context.WithTimeout(s.cctx.GoContext(), 30*time.Second) + defer cancel() + res, err := txClient.SubmitPayForBlob(subCtx, []*share.Blob{tc.blob}, user.SetGasLimitAndGasPrice(1e9, appconsts.DefaultMinGasPrice)) + require.Error(t, err) + require.Nil(t, res) + code := err.(*user.BroadcastTxError).Code + require.Equal(t, tc.expectedCode, code, err.Error(), tc.expectedErr) + }) + } + +} diff --git a/app/test/check_tx_test.go b/app/test/check_tx_test.go index bd894bbe23..44e47aea7f 100644 --- a/app/test/check_tx_test.go +++ b/app/test/check_tx_test.go @@ -11,6 +11,7 @@ import ( "github.com/celestiaorg/celestia-app/v3/app" "github.com/celestiaorg/celestia-app/v3/app/encoding" + apperr "github.com/celestiaorg/celestia-app/v3/app/errors" "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" "github.com/celestiaorg/celestia-app/v3/pkg/user" testutil "github.com/celestiaorg/celestia-app/v3/test/util" @@ -32,8 +33,6 @@ func TestCheckTx(t *testing.T) { ns1, err := share.NewV0Namespace(bytes.Repeat([]byte{1}, share.NamespaceVersionZeroIDSize)) require.NoError(t, err) - var genericErrorCode uint32 = 1 - accs := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"} testApp, kr := testutil.SetupTestAppWithGenesisValSet(app.DefaultConsensusParams(), accs...) @@ -99,6 +98,7 @@ func TestCheckTx(t *testing.T) { return bbtx }, expectedABCICode: blobtypes.ErrNamespaceMismatch.ABCICode(), + expectedLog: blobtypes.ErrNamespaceMismatch.Error(), }, { name: "PFB with no blob, CheckTxType_New", @@ -114,6 +114,7 @@ func TestCheckTx(t *testing.T) { return dtx.Tx }, expectedABCICode: blobtypes.ErrNoBlobs.ABCICode(), + expectedLog: blobtypes.ErrNoBlobs.Error(), }, { name: "normal blobTx w/ multiple blobs, CheckTxType_New", @@ -186,6 +187,7 @@ func TestCheckTx(t *testing.T) { return tx }, expectedABCICode: blobtypes.ErrBlobsTooLarge.ABCICode(), + expectedLog: blobtypes.ErrBlobsTooLarge.Error(), }, { name: "v1 blob with invalid signer", @@ -206,6 +208,7 @@ func TestCheckTx(t *testing.T) { return blobTxBytes }, expectedABCICode: blobtypes.ErrInvalidBlobSigner.ABCICode(), + expectedLog: blobtypes.ErrInvalidBlobSigner.Error(), }, { name: "v1 blob with valid signer", @@ -231,8 +234,8 @@ func TestCheckTx(t *testing.T) { require.NoError(t, err) return blobTx }, - expectedLog: "is larger than the application's configured threshold", - expectedABCICode: genericErrorCode, + expectedLog: apperr.ErrTxExceedsMaxSize.Error(), + expectedABCICode: apperr.ErrTxExceedsMaxSize.ABCICode(), }, { name: "v0 blob over 2MiB", @@ -245,8 +248,8 @@ func TestCheckTx(t *testing.T) { require.NoError(t, err) return blobTx }, - expectedLog: "is larger than the application's configured threshold", - expectedABCICode: genericErrorCode, + expectedLog: apperr.ErrTxExceedsMaxSize.Error(), + expectedABCICode: apperr.ErrTxExceedsMaxSize.ABCICode(), }, } From f0fca5b199fd988ef8e905c3551baeb36fe3e8fc Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 9 Dec 2024 16:09:35 +0100 Subject: [PATCH 11/13] style: lint --- app/check_tx.go | 3 ++- app/test/big_blob_test.go | 13 ++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/check_tx.go b/app/check_tx.go index e4adf62d2b..40d343617e 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -1,9 +1,10 @@ package app import ( - "cosmossdk.io/errors" "fmt" + "cosmossdk.io/errors" + apperr "github.com/celestiaorg/celestia-app/v3/app/errors" "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types" diff --git a/app/test/big_blob_test.go b/app/test/big_blob_test.go index 1892453b17..bbce473016 100644 --- a/app/test/big_blob_test.go +++ b/app/test/big_blob_test.go @@ -7,6 +7,7 @@ import ( "github.com/celestiaorg/celestia-app/v3/app" "github.com/celestiaorg/celestia-app/v3/app/encoding" + apperrors "github.com/celestiaorg/celestia-app/v3/app/errors" "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" "github.com/celestiaorg/celestia-app/v3/pkg/user" "github.com/celestiaorg/celestia-app/v3/test/util/testfactory" @@ -15,7 +16,6 @@ import ( "github.com/celestiaorg/go-square/v2/share" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - apperrors "github.com/celestiaorg/celestia-app/v3/app/errors" ) func TestBigBlobSuite(t *testing.T) { @@ -95,17 +95,17 @@ func (s *BigBlobSuite) TestBlobExceedsMaxTxSize() { t := s.T() type testCase struct { - name string - blob *share.Blob + name string + blob *share.Blob expectedCode uint32 expectedErr string } testCases := []testCase{ { - name: "2 MiB blob", - blob: newBlobWithSize(2097152), + name: "2 MiB blob", + blob: newBlobWithSize(2097152), expectedCode: apperrors.ErrTxExceedsMaxSize.ABCICode(), - expectedErr: apperrors.ErrTxExceedsMaxSize.Error(), + expectedErr: apperrors.ErrTxExceedsMaxSize.Error(), }, } @@ -123,5 +123,4 @@ func (s *BigBlobSuite) TestBlobExceedsMaxTxSize() { require.Equal(t, tc.expectedCode, code, err.Error(), tc.expectedErr) }) } - } From 0e99e30657340fa2a5f6f7878db04dce1d81e76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Wed, 11 Dec 2024 16:10:04 +0100 Subject: [PATCH 12/13] Update app/validate_txs.go Co-authored-by: Rootul P --- app/validate_txs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/validate_txs.go b/app/validate_txs.go index 346bcd7f45..2a63ef3695 100644 --- a/app/validate_txs.go +++ b/app/validate_txs.go @@ -36,7 +36,7 @@ func separateTxs(_ client.TxConfig, rawTxs [][]byte) ([][]byte, []*tx.BlobTx) { // // Side-effect: arranges all normal transactions before all blob transactions. func FilterTxs(logger log.Logger, ctx sdk.Context, handler sdk.AnteHandler, txConfig client.TxConfig, txs [][]byte) [][]byte { - // all transactions should be below the max tx size + // all transactions should be less than or equal to the max tx size maxTxSize := appconsts.MaxTxSize(ctx.BlockHeader().Version.App) //nolint:prealloc var txsBelowLimit [][]byte From 5cddecc314196fe8e5e1e444c687d16ee502ce56 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Wed, 11 Dec 2024 16:43:11 +0100 Subject: [PATCH 13/13] refactor: remove prepare proposal changes and cleanup check tx --- app/check_tx.go | 2 +- app/test/check_tx_test.go | 8 ------ app/test/prepare_proposal_test.go | 42 ++----------------------------- app/validate_txs.go | 17 +------------ 4 files changed, 4 insertions(+), 65 deletions(-) diff --git a/app/check_tx.go b/app/check_tx.go index 40d343617e..68ff288caa 100644 --- a/app/check_tx.go +++ b/app/check_tx.go @@ -23,7 +23,7 @@ func (app *App) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { maxTxSize := appconsts.MaxTxSize(app.AppVersion()) currentTxSize := len(tx) if currentTxSize > maxTxSize { - return sdkerrors.ResponseCheckTxWithEvents(errors.Wrapf(apperr.ErrTxExceedsMaxSize, "tx size %d bytes is larger than the application's configured threshold of %d bytes", currentTxSize, maxTxSize), 0, 0, []abci.Event{}, false) + return sdkerrors.ResponseCheckTxWithEvents(errors.Wrapf(apperr.ErrTxExceedsMaxSize, "tx size %d bytes is larger than the application's configured MaxTxSize of %d bytes for version %d", currentTxSize, maxTxSize, app.AppVersion()), 0, 0, []abci.Event{}, false) } // check if the transaction contains blobs diff --git a/app/test/check_tx_test.go b/app/test/check_tx_test.go index 44e47aea7f..87c7cc9e01 100644 --- a/app/test/check_tx_test.go +++ b/app/test/check_tx_test.go @@ -45,7 +45,6 @@ func TestCheckTx(t *testing.T) { checkType abci.CheckTxType getTx func() []byte expectedABCICode uint32 - expectedLog string } tests := []test{ @@ -98,7 +97,6 @@ func TestCheckTx(t *testing.T) { return bbtx }, expectedABCICode: blobtypes.ErrNamespaceMismatch.ABCICode(), - expectedLog: blobtypes.ErrNamespaceMismatch.Error(), }, { name: "PFB with no blob, CheckTxType_New", @@ -114,7 +112,6 @@ func TestCheckTx(t *testing.T) { return dtx.Tx }, expectedABCICode: blobtypes.ErrNoBlobs.ABCICode(), - expectedLog: blobtypes.ErrNoBlobs.Error(), }, { name: "normal blobTx w/ multiple blobs, CheckTxType_New", @@ -187,7 +184,6 @@ func TestCheckTx(t *testing.T) { return tx }, expectedABCICode: blobtypes.ErrBlobsTooLarge.ABCICode(), - expectedLog: blobtypes.ErrBlobsTooLarge.Error(), }, { name: "v1 blob with invalid signer", @@ -208,7 +204,6 @@ func TestCheckTx(t *testing.T) { return blobTxBytes }, expectedABCICode: blobtypes.ErrInvalidBlobSigner.ABCICode(), - expectedLog: blobtypes.ErrInvalidBlobSigner.Error(), }, { name: "v1 blob with valid signer", @@ -234,7 +229,6 @@ func TestCheckTx(t *testing.T) { require.NoError(t, err) return blobTx }, - expectedLog: apperr.ErrTxExceedsMaxSize.Error(), expectedABCICode: apperr.ErrTxExceedsMaxSize.ABCICode(), }, { @@ -248,7 +242,6 @@ func TestCheckTx(t *testing.T) { require.NoError(t, err) return blobTx }, - expectedLog: apperr.ErrTxExceedsMaxSize.Error(), expectedABCICode: apperr.ErrTxExceedsMaxSize.ABCICode(), }, } @@ -257,7 +250,6 @@ func TestCheckTx(t *testing.T) { t.Run(tt.name, func(t *testing.T) { resp := testApp.CheckTx(abci.RequestCheckTx{Type: tt.checkType, Tx: tt.getTx()}) assert.Equal(t, tt.expectedABCICode, resp.Code, resp.Log) - assert.Contains(t, resp.Log, tt.expectedLog) }) } } diff --git a/app/test/prepare_proposal_test.go b/app/test/prepare_proposal_test.go index aca70fb7d3..b167419a15 100644 --- a/app/test/prepare_proposal_test.go +++ b/app/test/prepare_proposal_test.go @@ -171,37 +171,6 @@ func TestPrepareProposalFiltering(t *testing.T) { // 3 transactions over MaxTxSize limit largeTxs := coretypes.Txs(testutil.SendTxsWithAccounts(t, testApp, encConf.TxConfig, kr, 1000, accounts[0], accounts[:3], testutil.ChainID, user.SetMemo(largeString))).ToSliceOfBytes() - maxTxSize := appconsts.MaxTxSize(testApp.AppVersion()) // max tx size for the latest version - // 3 blobTxs over MaxTxSize limit - largeBlobTxs := blobfactory.ManyMultiBlobTx( - t, - encConf.TxConfig, - kr, - testutil.ChainID, - accounts[:3], - infos[:3], - blobfactory.NestedBlobs( - t, - testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - [][]int{{maxTxSize + 1}, {maxTxSize + 1}, {maxTxSize + 1}}, - ), - ) - - // 3 blobTxs where one is over MaxTxSize limit - mixedSizeBlobTxs := blobfactory.ManyMultiBlobTx( - t, - encConf.TxConfig, - kr, - testutil.ChainID, - accounts[:3], - infos[:3], - blobfactory.NestedBlobs( - t, - testfactory.RandomBlobNamespaces(tmrand.NewRand(), 3), - [][]int{{2}, {2800}, {maxTxSize + 1}}, - ), - ) - type test struct { name string txs func() [][]byte @@ -256,16 +225,9 @@ func TestPrepareProposalFiltering(t *testing.T) { { name: "blobTxs and sendTxs that exceed MaxTxSize limit", txs: func() [][]byte { - return append(largeTxs, largeBlobTxs...) // All txs are over MaxTxSize limit - }, - prunedTxs: append(largeTxs, largeBlobTxs...), - }, - { - name: "blobTxs with mixed sizes, one is over MaxTxSize limit", - txs: func() [][]byte { - return mixedSizeBlobTxs + return largeTxs // All txs are over MaxTxSize limit }, - prunedTxs: [][]byte{mixedSizeBlobTxs[2]}, + prunedTxs: largeTxs, }, } diff --git a/app/validate_txs.go b/app/validate_txs.go index 346bcd7f45..ee3edfbb6f 100644 --- a/app/validate_txs.go +++ b/app/validate_txs.go @@ -1,8 +1,6 @@ package app import ( - "fmt" - "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" "github.com/celestiaorg/go-square/v2/tx" "github.com/cosmos/cosmos-sdk/client" @@ -36,20 +34,7 @@ func separateTxs(_ client.TxConfig, rawTxs [][]byte) ([][]byte, []*tx.BlobTx) { // // Side-effect: arranges all normal transactions before all blob transactions. func FilterTxs(logger log.Logger, ctx sdk.Context, handler sdk.AnteHandler, txConfig client.TxConfig, txs [][]byte) [][]byte { - // all transactions should be below the max tx size - maxTxSize := appconsts.MaxTxSize(ctx.BlockHeader().Version.App) - //nolint:prealloc - var txsBelowLimit [][]byte - for idx, tx := range txs { - if len(tx) > maxTxSize { - err := fmt.Sprintf("tx size %d bytes at index %d exceeds the application's configured threshold of %d bytes", len(tx), idx, maxTxSize) - logger.Error(err) - continue - } - txsBelowLimit = append(txsBelowLimit, tx) - } - - normalTxs, blobTxs := separateTxs(txConfig, txsBelowLimit) + normalTxs, blobTxs := separateTxs(txConfig, txs) normalTxs, ctx = filterStdTxs(logger, txConfig.TxDecoder(), ctx, handler, normalTxs) blobTxs, _ = filterBlobTxs(logger, txConfig.TxDecoder(), ctx, handler, blobTxs) return append(normalTxs, encodeBlobTxs(blobTxs)...)