diff --git a/app/default_overrides.go b/app/default_overrides.go index f0e7d13cba..969b5604d8 100644 --- a/app/default_overrides.go +++ b/app/default_overrides.go @@ -259,12 +259,12 @@ func DefaultConsensusConfig() *tmcfg.Config { cfg := tmcfg.DefaultConfig() // Set broadcast timeout to be 50 seconds in order to avoid timeouts for long block times cfg.RPC.TimeoutBroadcastTxCommit = 50 * time.Second - cfg.RPC.MaxBodyBytes = int64(8388608) // 8 MiB + cfg.RPC.MaxBodyBytes = int64(83886080) // 8 MiB cfg.Mempool.TTLNumBlocks = 12 cfg.Mempool.TTLDuration = 75 * time.Second - cfg.Mempool.MaxTxBytes = 7_897_088 - cfg.Mempool.MaxTxsBytes = 39_485_440 + cfg.Mempool.MaxTxBytes = 7_897_088_000 + cfg.Mempool.MaxTxsBytes = 39_485_440_000 cfg.Mempool.Version = "v1" // prioritized mempool cfg.Consensus.TimeoutPropose = appconsts.GetTimeoutPropose(appconsts.LatestVersion) @@ -275,8 +275,8 @@ func DefaultConsensusConfig() *tmcfg.Config { cfg.Storage.DiscardABCIResponses = true const mebibyte = 1048576 - cfg.P2P.SendRate = 10 * mebibyte - cfg.P2P.RecvRate = 10 * mebibyte + cfg.P2P.SendRate = 1000 * mebibyte + cfg.P2P.RecvRate = 1000 * mebibyte return cfg } @@ -296,6 +296,6 @@ func DefaultAppConfig() *serverconfig.Config { cfg.MinGasPrices = fmt.Sprintf("%v%s", appconsts.DefaultMinGasPrice, BondDenom) const mebibyte = 1048576 - cfg.GRPC.MaxRecvMsgSize = 20 * mebibyte + cfg.GRPC.MaxRecvMsgSize = 40 * mebibyte return cfg } diff --git a/celestia-appd.service b/celestia-appd.service new file mode 100644 index 0000000000..616e6fc295 --- /dev/null +++ b/celestia-appd.service @@ -0,0 +1,15 @@ +[Unit] +Description=Generate chain and run +After=network.target + +[Service] +Type=simple +Environment="PATH=/usr/local/go/bin:/root/go/bin:/usr/bin:/bin" +ExecStart=/root/go/bin/celestia-appd start --minimum-gas-prices 0.000001utia --home /root/chainbuilder/generated/celestia-app/testnode-32mb-100k --grpc.enable +User=root +Restart=always +RestartSec=3 +WorkingDirectory=/root/chainbuilder/generated/celestia-app + +[Install] +WantedBy=multi-user.target diff --git a/chainbuilder.service b/chainbuilder.service new file mode 100644 index 0000000000..19ff710c78 --- /dev/null +++ b/chainbuilder.service @@ -0,0 +1,14 @@ +[Unit] +Description=Generate chain and run +After=network.target + +[Service] +Type=simple +Environment="PATH=/usr/local/go/bin:/root/go/bin:/usr/bin:/bin" +ExecStart=/root/chainbuilder/generated/celestia-app/run.sh +User=root +WorkingDirectory=/root/chainbuilder/generated/celestia-app +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/cmd/celestia-appd/cmd/start.go b/cmd/celestia-appd/cmd/start.go index 057ae4422a..e3034a55f3 100644 --- a/cmd/celestia-appd/cmd/start.go +++ b/cmd/celestia-appd/cmd/start.go @@ -5,6 +5,7 @@ package cmd import ( "fmt" + db "github.com/cometbft/cometbft-db" "io" "net" "net/http" @@ -257,6 +258,14 @@ func startStandAlone(ctx *server.Context, appCreator srvrtypes.AppCreator) error return server.WaitForQuitSignals() } +func dbProvider(ctx *node.DBContext) (db.DB, error) { + blockDB, err := db.NewDB(ctx.ID, db.PebbleDBBackend, ctx.Config.DBDir()) + if err != nil { + return nil, err + } + return blockDB, nil +} + func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator srvrtypes.AppCreator) error { cfg := ctx.Config home := cfg.RootDir @@ -307,7 +316,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator sr nodeKey, proxy.NewLocalClientCreator(app), genDocProvider, - node.DefaultDBProvider, + dbProvider, node.DefaultMetricsProvider(cfg.Instrumentation), ctx.Logger, ) diff --git a/generate_script.sh b/generate_script.sh new file mode 100644 index 0000000000..d72b21f4f5 --- /dev/null +++ b/generate_script.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +go run ./tools/chainbuilder --num-blocks 100000 --block-size 32000000 --chain-id 32mb-100k + +systemctl daemon-reload +systemctl start txsim + +celestia-appd start --minimum-gas-prices 0.000001utia --home ~/chainbuilder/generated/celestia-app/testnode-32mb-100k --grpc.enable diff --git a/pkg/appconsts/initial_consts.go b/pkg/appconsts/initial_consts.go index c9924f5174..bfbe37c7cd 100644 --- a/pkg/appconsts/initial_consts.go +++ b/pkg/appconsts/initial_consts.go @@ -11,7 +11,7 @@ import ( const ( // DefaultGovMaxSquareSize is the default value for the governance modifiable // max square size. - DefaultGovMaxSquareSize = 64 + DefaultGovMaxSquareSize = 256 // DefaultMaxBytes is the default value for the governance modifiable // maximum number of bytes allowed in a valid block. diff --git a/pkg/appconsts/v3/app_consts.go b/pkg/appconsts/v3/app_consts.go index e5b660bf2e..0afaf2c393 100644 --- a/pkg/appconsts/v3/app_consts.go +++ b/pkg/appconsts/v3/app_consts.go @@ -4,11 +4,11 @@ import "time" const ( Version uint64 = 3 - SquareSizeUpperBound int = 128 + SquareSizeUpperBound int = 512 SubtreeRootThreshold int = 64 TxSizeCostPerByte uint64 = 10 GasPerBlobByte uint32 = 8 - MaxTxSize int = 2097152 // 2 MiB in bytes + MaxTxSize int = 409715200 // 2 MiB in bytes TimeoutPropose = time.Millisecond * 3500 TimeoutCommit = time.Millisecond * 4200 // UpgradeHeightDelay is the number of blocks after a quorum has been diff --git a/tools/chainbuilder/README.md b/tools/chainbuilder/README.md index 50ceb3c06d..eee54c36bc 100644 --- a/tools/chainbuilder/README.md +++ b/tools/chainbuilder/README.md @@ -10,7 +10,7 @@ Use `go` to run the binary as follows: go run ./tools/chainbuilder ``` -This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterwards by calling: +This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterward by calling: ```shell celestia-appd start --home /path/to/testnode-{chainID} @@ -19,9 +19,8 @@ celestia-appd start --home /path/to/testnode-{chainID} The following are the set of options when generating a chain: - `num-blocks` the number of blocks to be generated (default: 100) -- `block-size` the size of the blocks to be generated (default <2MB). This will be a single PFB transaction -- `square-size` the size of the max square (default: 128) +- `block-size` the size of the blocks to be generated in bytes (default <2MB). This will be a single PFB transaction - `existing-dir` point this to a directory if you want to extend an existing chain rather than create a new one -- `namespace` allows you to pick a custom v0 namespace. By default "test" will be chosen. +- `namespace` allows you to pick a custom v0 namespace. By default, "test" will be chosen. This tool takes roughly 60-70ms per 2MB block. diff --git a/tools/chainbuilder/main.go b/tools/chainbuilder/main.go index 914706ba01..ec8754d6fa 100644 --- a/tools/chainbuilder/main.go +++ b/tools/chainbuilder/main.go @@ -3,10 +3,13 @@ package main import ( "context" "fmt" + "math/rand" "os" "path/filepath" "time" + blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types" + "github.com/celestiaorg/go-square/v2" "github.com/celestiaorg/go-square/v2/share" dbm "github.com/cometbft/cometbft-db" @@ -34,11 +37,37 @@ import ( "github.com/celestiaorg/celestia-app/v3/test/util" "github.com/celestiaorg/celestia-app/v3/test/util/genesis" "github.com/celestiaorg/celestia-app/v3/test/util/testnode" - blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types" ) var defaultNamespace share.Namespace +// emptyBlockData contains the protobuf block data for a block without transactions. +var emptyBlockData = func() tmproto.Data { + dataSquare, txs, err := square.Build( + [][]byte{}, + maxSquareSize, + appconsts.SubtreeRootThreshold(1), + ) + if err != nil { + panic(err) + } + + eds, err := da.ExtendShares(share.ToBytes(dataSquare)) + if err != nil { + panic(err) + } + + dah, err := da.NewDataAvailabilityHeader(eds) + if err != nil { + panic(err) + } + return tmproto.Data{ + Txs: txs, + Hash: dah.Hash(), + SquareSize: uint64(dataSquare.Size()), + } +}() + const ( defaultNamespaceStr = "test" maxSquareSize = 512 @@ -175,14 +204,14 @@ func Run(ctx context.Context, cfg BuilderConfig, dir string) error { validatorKey := privval.LoadFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()) validatorAddr := validatorKey.Key.Address - blockDB, err := dbm.NewDB("blockstore", dbm.GoLevelDBBackend, tmCfg.DBDir()) + blockDB, err := dbm.NewDB("blockstore", dbm.PebbleDBBackend, tmCfg.DBDir()) if err != nil { return fmt.Errorf("failed to create block database: %w", err) } blockStore := store.NewBlockStore(blockDB) - stateDB, err := dbm.NewDB("state", dbm.GoLevelDBBackend, tmCfg.DBDir()) + stateDB, err := dbm.NewDB("state", dbm.PebbleDBBackend, tmCfg.DBDir()) if err != nil { return fmt.Errorf("failed to create state database: %w", err) } @@ -321,108 +350,116 @@ func Run(ctx context.Context, cfg BuilderConfig, dir string) error { break } - select { - case <-ctx.Done(): - return ctx.Err() - case dataPB := <-dataCh: - data, err := types.DataFromProto(dataPB) - if err != nil { - return fmt.Errorf("failed to convert data from protobuf: %w", err) - } - block, blockParts := state.MakeBlock(height, data, commit, nil, validatorAddr) - blockID := types.BlockID{ - Hash: block.Hash(), - PartSetHeader: blockParts.Header(), + var dd *tmproto.Data + if height == 1 { + // generating an empty block for height 1 + dd = &emptyBlockData + } else { + select { + case <-ctx.Done(): + return ctx.Err() + case dataPB := <-dataCh: + dd = dataPB } + } - precommitVote := &tmproto.Vote{ - Height: height, - Round: 0, - Type: tmproto.PrecommitType, - BlockID: blockID.ToProto(), - ValidatorAddress: validatorAddr, - Timestamp: currentTime, - Signature: nil, - } + data, err := types.DataFromProto(dd) + if err != nil { + return fmt.Errorf("failed to convert data from protobuf: %w", err) + } + block, blockParts := state.MakeBlock(height, data, commit, nil, validatorAddr) + blockID := types.BlockID{ + Hash: block.Hash(), + PartSetHeader: blockParts.Header(), + } - if err := validatorKey.SignVote(state.ChainID, precommitVote); err != nil { - return fmt.Errorf("failed to sign precommit vote (%s): %w", precommitVote.String(), err) - } + precommitVote := &tmproto.Vote{ + Height: height, + Round: 0, + Type: tmproto.PrecommitType, + BlockID: blockID.ToProto(), + ValidatorAddress: validatorAddr, + Timestamp: currentTime, + Signature: nil, + } - commitSig := types.CommitSig{ - BlockIDFlag: types.BlockIDFlagCommit, - ValidatorAddress: validatorAddr, - Timestamp: currentTime, - Signature: precommitVote.Signature, - } - commit = types.NewCommit(height, 0, blockID, []types.CommitSig{commitSig}) - - var lastCommitInfo abci.LastCommitInfo - if height > 1 { - lastCommitInfo = abci.LastCommitInfo{ - Round: 0, - Votes: []abci.VoteInfo{ - { - Validator: abci.Validator{ - Address: validatorAddr, - Power: validatorPower, - }, - SignedLastBlock: true, + if err := validatorKey.SignVote(state.ChainID, precommitVote); err != nil { + return fmt.Errorf("failed to sign precommit vote (%s): %w", precommitVote.String(), err) + } + + commitSig := types.CommitSig{ + BlockIDFlag: types.BlockIDFlagCommit, + ValidatorAddress: validatorAddr, + Timestamp: currentTime, + Signature: precommitVote.Signature, + } + commit = types.NewCommit(height, 0, blockID, []types.CommitSig{commitSig}) + + var lastCommitInfo abci.LastCommitInfo + if height > 1 { + lastCommitInfo = abci.LastCommitInfo{ + Round: 0, + Votes: []abci.VoteInfo{ + { + Validator: abci.Validator{ + Address: validatorAddr, + Power: validatorPower, }, + SignedLastBlock: true, }, - } + }, } + } - beginBlockResp := simApp.BeginBlock(abci.RequestBeginBlock{ - Hash: block.Hash(), - Header: *block.Header.ToProto(), - LastCommitInfo: lastCommitInfo, - }) + beginBlockResp := simApp.BeginBlock(abci.RequestBeginBlock{ + Hash: block.Hash(), + Header: *block.Header.ToProto(), + LastCommitInfo: lastCommitInfo, + }) - deliverTxResponses := make([]*abci.ResponseDeliverTx, len(block.Data.Txs)) + deliverTxResponses := make([]*abci.ResponseDeliverTx, len(block.Data.Txs)) - for idx, tx := range block.Data.Txs { - blobTx, isBlobTx := types.UnmarshalBlobTx(tx) - if isBlobTx { - tx = blobTx.Tx - } - deliverTxResponse := simApp.DeliverTx(abci.RequestDeliverTx{ - Tx: tx, - }) - if deliverTxResponse.Code != abci.CodeTypeOK { - return fmt.Errorf("failed to deliver tx: %s", deliverTxResponse.Log) - } - deliverTxResponses[idx] = &deliverTxResponse + for idx, tx := range block.Data.Txs { + blobTx, isBlobTx := types.UnmarshalBlobTx(tx) + if isBlobTx { + tx = blobTx.Tx } - - endBlockResp := simApp.EndBlock(abci.RequestEndBlock{ - Height: block.Height, - }) - - commitResp := simApp.Commit() - state.LastBlockHeight = height - state.LastBlockID = blockID - state.LastBlockTime = block.Time - state.LastValidators = state.Validators - state.Validators = state.NextValidators - state.NextValidators = state.NextValidators.CopyIncrementProposerPriority(1) - state.AppHash = commitResp.Data - state.LastResultsHash = sm.ABCIResponsesResultsHash(&smproto.ABCIResponses{ - DeliverTxs: deliverTxResponses, - BeginBlock: &beginBlockResp, - EndBlock: &endBlockResp, + deliverTxResponse := simApp.DeliverTx(abci.RequestDeliverTx{ + Tx: tx, }) - currentTime = currentTime.Add(cfg.BlockInterval) - persistCh <- persistData{ - state: state.Copy(), - block: block, - seenCommit: &types.Commit{ - Height: commit.Height, - Round: commit.Round, - BlockID: commit.BlockID, - Signatures: []types.CommitSig{commitSig}, - }, + if deliverTxResponse.Code != abci.CodeTypeOK { + return fmt.Errorf("failed to deliver tx: %s", deliverTxResponse.Log) } + deliverTxResponses[idx] = &deliverTxResponse + } + + endBlockResp := simApp.EndBlock(abci.RequestEndBlock{ + Height: block.Height, + }) + + commitResp := simApp.Commit() + state.LastBlockHeight = height + state.LastBlockID = blockID + state.LastBlockTime = block.Time + state.LastValidators = state.Validators + state.Validators = state.NextValidators + state.NextValidators = state.NextValidators.CopyIncrementProposerPriority(1) + state.AppHash = commitResp.Data + state.LastResultsHash = sm.ABCIResponsesResultsHash(&smproto.ABCIResponses{ + DeliverTxs: deliverTxResponses, + BeginBlock: &beginBlockResp, + EndBlock: &endBlockResp, + }) + currentTime = currentTime.Add(cfg.BlockInterval) + persistCh <- persistData{ + state: state.Copy(), + block: block, + seenCommit: &types.Commit{ + Height: commit.Height, + Round: commit.Round, + BlockID: commit.BlockID, + Signatures: []types.CommitSig{commitSig}, + }, } } @@ -458,7 +495,8 @@ func generateSquareRoutine( cfg BuilderConfig, dataCh chan<- *tmproto.Data, ) error { - for i := 0; i < cfg.NumBlocks; i++ { + // cfg.NumBlocks-1 because block 0 is genesis and block 1 shouldn't contain any transaction + for i := 0; i < cfg.NumBlocks-1; i++ { select { case <-ctx.Done(): return ctx.Err() @@ -467,23 +505,29 @@ func generateSquareRoutine( account := signer.Accounts()[0] - blob, err := share.NewV0Blob(cfg.Namespace, crypto.CRandBytes(cfg.BlockSize)) - if err != nil { - return err - } + blobTxs := make([][]byte, 0) + numberOfBlobs := rand.Intn(100) + 1 + blobSize := cfg.BlockSize / numberOfBlobs + for size := 0; size < cfg.BlockSize; size += blobSize { + blob, err := share.NewV0Blob(share.RandomNamespace(), crypto.CRandBytes(blobSize)) + if err != nil { + return err + } - blobGas := blobtypes.DefaultEstimateGas([]uint32{uint32(cfg.BlockSize)}) - fee := float64(blobGas) * appconsts.DefaultMinGasPrice * 2 - tx, _, err := signer.CreatePayForBlobs(account.Name(), []*share.Blob{blob}, user.SetGasLimit(blobGas), user.SetFee(uint64(fee))) - if err != nil { - return err - } - if err := signer.IncrementSequence(account.Name()); err != nil { - return err + blobGas := blobtypes.DefaultEstimateGas([]uint32{uint32(blobSize)}) + fee := float64(blobGas) * appconsts.DefaultMinGasPrice * 2 + tx, _, err := signer.CreatePayForBlobs(account.Name(), []*share.Blob{blob}, user.SetGasLimit(blobGas), user.SetFee(uint64(fee))) + if err != nil { + return err + } + if err := signer.IncrementSequence(account.Name()); err != nil { + return err + } + blobTxs = append(blobTxs, tx) } dataSquare, txs, err := square.Build( - [][]byte{tx}, + blobTxs, maxSquareSize, appconsts.SubtreeRootThreshold(1), ) diff --git a/txsim.service b/txsim.service new file mode 100644 index 0000000000..e551485537 --- /dev/null +++ b/txsim.service @@ -0,0 +1,15 @@ +[Unit] +Description=TxSim Service +After=network.target + +[Service] +Type=simple +Environment="PATH=/usr/local/go/bin:/root/go/bin:/usr/bin:/bin" +ExecStart=/root/go/bin/txsim --blob-sizes 3000000-30000000 --grpc-endpoint localhost:9090 --blob 10 --key-path /root/chainbuilder/generated/celestia-app/testnode-32mb-100k --master validator +Restart=always +RestartSec=3 +User=root +WorkingDirectory=/home/ubuntu + +[Install] +WantedBy=multi-user.target