Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: support authored blobs #3765

Merged
merged 13 commits into from
Aug 13, 2024
3 changes: 2 additions & 1 deletion app/default_overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/celestiaorg/celestia-app/v3/pkg/appconsts"
"github.com/celestiaorg/celestia-app/v3/x/mint"
minttypes "github.com/celestiaorg/celestia-app/v3/x/mint/types"
"github.com/celestiaorg/go-square/v2/share"
"github.com/cosmos/cosmos-sdk/codec"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -268,7 +269,7 @@ func DefaultConsensusConfig() *tmcfg.Config {
// We set a loose upper bound on what we expect the transaction to
// be based on the upper bound size of the entire block for the given
// version. This acts as a first line of DoS protection
upperBoundBytes := appconsts.DefaultSquareSizeUpperBound * appconsts.DefaultSquareSizeUpperBound * appconsts.ContinuationSparseShareContentSize
upperBoundBytes := appconsts.DefaultSquareSizeUpperBound * appconsts.DefaultSquareSizeUpperBound * share.ContinuationSparseShareContentSize
cfg.Mempool.MaxTxBytes = upperBoundBytes
cfg.Mempool.MaxTxsBytes = int64(upperBoundBytes) * cfg.Mempool.TTLNumBlocks
cfg.Mempool.Version = "v1" // prioritized mempool
Expand Down
2 changes: 1 addition & 1 deletion app/errors/insufficient_gas_price_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestInsufficientMinGasPriceIntegration(t *testing.T) {
signer, err := user.NewSigner(kr, enc.TxConfig, testutil.ChainID, appconsts.LatestVersion, user.NewAccount(account, acc.GetAccountNumber(), acc.GetSequence()))
require.NoError(t, err)

b, err := blob.NewBlob(share.RandomNamespace(), []byte("hello world"), 0)
b, err := blob.NewV0Blob(share.RandomNamespace(), []byte("hello world"))
require.NoError(t, err)

msg, err := blob.NewMsgPayForBlobs(signer.Account(account).Address().String(), appconsts.LatestVersion, b)
Expand Down
2 changes: 1 addition & 1 deletion app/errors/nonce_mismatch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestNonceMismatchIntegration(t *testing.T) {
signer, err := user.NewSigner(kr, enc.TxConfig, testutil.ChainID, appconsts.LatestVersion, user.NewAccount(account, acc.GetAccountNumber(), acc.GetSequence()+1))
require.NoError(t, err)

b, err := blob.NewBlob(share.RandomNamespace(), []byte("hello world"), 0)
b, err := blob.NewV0Blob(share.RandomNamespace(), []byte("hello world"))
require.NoError(t, err)

msg, err := blob.NewMsgPayForBlobs(signer.Account(account).Address().String(), appconsts.LatestVersion, b)
Expand Down
30 changes: 29 additions & 1 deletion app/test/check_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
tmrand "github.com/tendermint/tendermint/libs/rand"

"github.com/celestiaorg/celestia-app/v3/app"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/celestiaorg/celestia-app/v3/pkg/user"
testutil "github.com/celestiaorg/celestia-app/v3/test/util"
"github.com/celestiaorg/celestia-app/v3/test/util/blobfactory"
"github.com/celestiaorg/celestia-app/v3/test/util/testnode"
blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types"
"github.com/celestiaorg/go-square/v2/share"
"github.com/celestiaorg/go-square/v2/tx"
Expand All @@ -30,7 +32,7 @@ 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"}
accs := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}

testApp, kr := testutil.SetupTestAppWithGenesisValSet(app.DefaultConsensusParams(), accs...)
testApp.Commit()
Expand Down Expand Up @@ -182,6 +184,32 @@ func TestCheckTx(t *testing.T) {
},
expectedABCICode: blobtypes.ErrBlobsTooLarge.ABCICode(),
},
{
name: "v1 blob with invalid signer",
checkType: abci.CheckTxType_New,
getTx: func() []byte {
signer := createSigner(t, kr, accs[10], encCfg.TxConfig, 11)
blob, err := share.NewV1Blob(share.RandomBlobNamespace(), []byte("data"), testnode.RandomAddress().(sdk.AccAddress))
require.NoError(t, err)
blobTx, _, err := signer.CreatePayForBlobs(accs[10], []*share.Blob{blob}, opts...)
require.NoError(t, err)
return blobTx
},
expectedABCICode: blobtypes.ErrInvalidBlobSigner.ABCICode(),
},
{
name: "v1 blob with valid signer",
checkType: abci.CheckTxType_New,
getTx: func() []byte {
signer := createSigner(t, kr, accs[10], encCfg.TxConfig, 11)
blob, err := share.NewV1Blob(share.RandomBlobNamespace(), []byte("data"), 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: abci.CodeTypeOK,
},
}

for _, tt := range tests {
Expand Down
3 changes: 3 additions & 0 deletions app/test/consistent_apphash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ func executeTxs(testApp *app.App, encodedBlobTx []byte, encodedSdkTxs [][]byte,
// Dynamically increase time so the validator can be unjailed (1m duration)
Time: genesisTime.Add(time.Duration(height) * time.Minute),
})
if len(resPrepareProposal.BlockData.Txs) != len(encodedSdkTxs) {
return nil, nil, fmt.Errorf("PrepareProposal removed transactions. Was %d, now %d", len(encodedSdkTxs), len(resPrepareProposal.BlockData.Txs))
}

dataHash := resPrepareProposal.BlockData.Hash

Expand Down
7 changes: 4 additions & 3 deletions app/test/fuzz_abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"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"
"github.com/celestiaorg/go-square/v2/share"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmrand "github.com/tendermint/tendermint/libs/rand"
Expand Down Expand Up @@ -62,17 +63,17 @@ func TestPrepareProposalConsistency(t *testing.T) {
},
{
"max",
maxShareCount * appconsts.ContinuationSparseShareContentSize,
maxShareCount * share.ContinuationSparseShareContentSize,
appconsts.DefaultSquareSizeUpperBound,
},
{
"larger MaxBytes than SquareSize",
maxShareCount * appconsts.ContinuationSparseShareContentSize,
maxShareCount * share.ContinuationSparseShareContentSize,
appconsts.DefaultGovMaxSquareSize,
},
{
"smaller MaxBytes than SquareSize",
32 * 32 * appconsts.ContinuationSparseShareContentSize,
32 * 32 * share.ContinuationSparseShareContentSize,
appconsts.DefaultGovMaxSquareSize,
},
}
Expand Down
2 changes: 1 addition & 1 deletion app/test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func (s *IntegrationTestSuite) TestEmptyBlock() {
func newBlobWithSize(size int) *share.Blob {
ns := share.MustNewV0Namespace(bytes.Repeat([]byte{1}, share.NamespaceVersionZeroIDSize))
data := tmrand.Bytes(size)
blob, err := share.NewBlob(ns, data, appconsts.ShareVersionZero, nil)
blob, err := share.NewBlob(ns, data, share.ShareVersionZero, nil)
if err != nil {
panic(err)
}
Expand Down
44 changes: 42 additions & 2 deletions app/test/process_proposal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
Expand All @@ -24,6 +25,8 @@ import (
testutil "github.com/celestiaorg/celestia-app/v3/test/util"
"github.com/celestiaorg/celestia-app/v3/test/util/blobfactory"
"github.com/celestiaorg/celestia-app/v3/test/util/testfactory"
"github.com/celestiaorg/celestia-app/v3/test/util/testnode"
blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types"
"github.com/celestiaorg/go-square/v2"
"github.com/celestiaorg/go-square/v2/share"
"github.com/celestiaorg/go-square/v2/tx"
Expand Down Expand Up @@ -117,7 +120,7 @@ func TestProcessProposal(t *testing.T) {
mutator: func(d *tmproto.Data) {
blobTx, _, err := tx.UnmarshalBlobTx(blobTxs[0])
require.NoError(t, err)
newBlob, err := share.NewBlob(ns1, data, appconsts.ShareVersionZero, nil)
newBlob, err := share.NewBlob(ns1, data, share.ShareVersionZero, nil)
require.NoError(t, err)
blobTx.Blobs[0] = newBlob
blobTxBytes, _ := tx.MarshalBlobTx(blobTx.Tx, blobTx.Blobs...)
Expand All @@ -132,7 +135,7 @@ func TestProcessProposal(t *testing.T) {
mutator: func(d *tmproto.Data) {
blobTx, _, err := tx.UnmarshalBlobTx(blobTxs[0])
require.NoError(t, err)
newBlob, err := share.NewBlob(share.TxNamespace, data, appconsts.ShareVersionZero, nil)
newBlob, err := share.NewBlob(share.TxNamespace, data, share.ShareVersionZero, nil)
require.NoError(t, err)
blobTx.Blobs[0] = newBlob
blobTxBytes, _ := tx.MarshalBlobTx(blobTx.Tx, blobTx.Blobs...)
Expand Down Expand Up @@ -259,6 +262,43 @@ func TestProcessProposal(t *testing.T) {
appVersion: appconsts.LatestVersion,
expectedResult: abci.ResponseProcessProposal_REJECT,
},
{
name: "valid v1 authored blob",
input: validData(),
mutator: func(d *tmproto.Data) {
addr := signer.Account(accounts[0]).Address()
blob, err := share.NewV1Blob(ns1, data, addr)
require.NoError(t, err)
rawTx, _, err := signer.CreatePayForBlobs(accounts[0], []*share.Blob{blob}, user.SetGasLimit(100000), user.SetFee(100000))
require.NoError(t, err)
d.Txs[0] = rawTx
d.Hash = calculateNewDataHash(t, d.Txs)
},
appVersion: appconsts.LatestVersion,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocking] I think this test case should fail b/c app version is 2. Should this feature be gated behind an app version bump?

Ref: https://github.com/celestiaorg/CIPs/blob/main/cips/cip-21.md#backwards-compatibility

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was waiting on this until we have more information regarding your v3 prototype. At the moment it's not gated but it should be

expectedResult: abci.ResponseProcessProposal_ACCEPT,
},
{
name: "v1 authored blob with invalid signer",
input: validData(),
mutator: func(d *tmproto.Data) {
addr := signer.Account(accounts[0]).Address()
falseAddr := testnode.RandomAddress().(sdk.AccAddress)
blob, err := share.NewV1Blob(ns1, data, falseAddr)
require.NoError(t, err)
msg, err := blobtypes.NewMsgPayForBlobs(addr.String(), appconsts.LatestVersion, blob)
require.NoError(t, err)

rawTx, err := signer.CreateTx([]sdk.Msg{msg}, user.SetGasLimit(100000), user.SetFee(100000))
require.NoError(t, err)

blobTxBytes, err := tx.MarshalBlobTx(rawTx, blob)
require.NoError(t, err)
d.Txs[0] = blobTxBytes
d.Hash = calculateNewDataHash(t, d.Txs)
},
appVersion: appconsts.LatestVersion,
expectedResult: abci.ResponseProcessProposal_REJECT,
},
}

for _, tt := range tests {
Expand Down
2 changes: 1 addition & 1 deletion app/test/square_size_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (s *SquareSizeIntegrationTest) TestSquareSizeUpperBound() {
{
name: "gov square size == hardcoded max",
govMaxSquareSize: appconsts.DefaultSquareSizeUpperBound,
maxBytes: appconsts.DefaultSquareSizeUpperBound * appconsts.DefaultSquareSizeUpperBound * appconsts.ContinuationSparseShareContentSize,
maxBytes: appconsts.DefaultUpperBoundMaxBytes,
expectedMaxSquareSize: appconsts.DefaultSquareSizeUpperBound,
},
}
Expand Down
2 changes: 1 addition & 1 deletion app/test/std_sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ func (s *StandardSDKIntegrationTestSuite) TestGRPCQueries() {

txSubmitter, err := user.SetupTxClient(s.cctx.GoContext(), s.cctx.Keyring, s.cctx.GRPCClient, s.ecfg)
require.NoError(t, err)
blobs := blobfactory.RandBlobsWithNamespace([]share.Namespace{share.RandomNamespace()}, []int{1000})
blobs := blobfactory.RandV0BlobsWithNamespace([]share.Namespace{share.RandomNamespace()}, []int{1000})
res, err := txSubmitter.SubmitPayForBlob(s.cctx.GoContext(), blobs, blobfactory.DefaultTxOpts()...)
require.NoError(t, err)

Expand Down
57 changes: 3 additions & 54 deletions pkg/appconsts/global_consts.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package appconsts

import (
"math"

ns "github.com/celestiaorg/go-square/v2/share"
"github.com/celestiaorg/go-square/v2/share"
"github.com/celestiaorg/rsmt2d"
"github.com/tendermint/tendermint/pkg/consts"
)
Expand All @@ -13,55 +11,9 @@ import (
//
// They can not change throughout the lifetime of a network.
const (
// NamespaceVersionSize is the size of a namespace version in bytes.
NamespaceVersionSize = ns.NamespaceVersionSize
// NamespaceVersionMaxValue is the maximum value a namespace version can be.
// This const must be updated if NamespaceVersionSize is changed.
NamespaceVersionMaxValue = math.MaxUint8

// NamespaceIDSize is the size of a namespace ID in bytes.
NamespaceIDSize = ns.NamespaceIDSize

// NamespaceSize is the size of a namespace (version + ID) in bytes.
NamespaceSize = ns.NamespaceSize

// ShareSize is the size of a share in bytes.
ShareSize = 512

// ShareInfoBytes is the number of bytes reserved for information. The info
// byte contains the share version and a sequence start indicator.
ShareInfoBytes = 1

// SequenceLenBytes is the number of bytes reserved for the sequence length
// that is present in the first share of a sequence.
SequenceLenBytes = 4

// ShareVersionZero is the first share version format.
ShareVersionZero = uint8(0)
cmwaters marked this conversation as resolved.
Show resolved Hide resolved

// DefaultShareVersion is the defacto share version. Use this if you are
// unsure of which version to use.
DefaultShareVersion = ShareVersionZero

// CompactShareReservedBytes is the number of bytes reserved for the location of
// the first unit (transaction, ISR) in a compact share.
CompactShareReservedBytes = 4

// FirstCompactShareContentSize is the number of bytes usable for data in
// the first compact share of a sequence.
FirstCompactShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes - SequenceLenBytes - CompactShareReservedBytes

// ContinuationCompactShareContentSize is the number of bytes usable for
// data in a continuation compact share of a sequence.
ContinuationCompactShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes - CompactShareReservedBytes

// FirstSparseShareContentSize is the number of bytes usable for data in the
// first sparse share of a sequence.
FirstSparseShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes - SequenceLenBytes

// ContinuationSparseShareContentSize is the number of bytes usable for data
// in a continuation sparse share of a sequence.
ContinuationSparseShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes
DefaultShareVersion = share.ShareVersionZero
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] why default to the previous share version when a new one exists?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't know what is meant by the default here. I have left it as is because v1 is a new feature and I a) don't know if many people will use it and b) should be opt in anyway.

Maybe if this is just for tests we can change it but it would require a large refactor since the new version requires new arguments


// MinSquareSize is the smallest original square width.
MinSquareSize = 1
Expand All @@ -70,9 +22,6 @@ const (
// data square.
MinShareCount = MinSquareSize * MinSquareSize

// MaxShareVersion is the maximum value a share version can be.
MaxShareVersion = 127

// BondDenom defines the native staking denomination
BondDenom = "utia"
)
Expand All @@ -92,7 +41,7 @@ var (
DefaultCodec = rsmt2d.NewLeoRSCodec

// SupportedShareVersions is a list of supported share versions.
SupportedShareVersions = []uint8{ShareVersionZero}
SupportedShareVersions = share.SupportedShareVersions
)

// HashLength returns the length of a hash in bytes.
Expand Down
10 changes: 8 additions & 2 deletions pkg/appconsts/initial_consts.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package appconsts

import "time"
import (
"time"

"github.com/celestiaorg/go-square/v2/share"
)

// The following defaults correspond to initial parameters of the network that can be changed, not via app versions
// but other means such as on-chain governance, or the nodes local config
Expand All @@ -11,7 +15,7 @@ const (

// DefaultMaxBytes is the default value for the governance modifiable
// maximum number of bytes allowed in a valid block.
DefaultMaxBytes = DefaultGovMaxSquareSize * DefaultGovMaxSquareSize * ContinuationSparseShareContentSize
DefaultMaxBytes = DefaultGovMaxSquareSize * DefaultGovMaxSquareSize * share.ContinuationSparseShareContentSize

// DefaultGasPerBlobByte is the default gas cost deducted per byte of blob
// included in a PayForBlobs txn
Expand All @@ -27,3 +31,5 @@ const (
// time can be subject to slashing under conditions of misbehavior.
DefaultUnbondingTime = 3 * 7 * 24 * time.Hour
)

var DefaultUpperBoundMaxBytes = DefaultSquareSizeUpperBound * DefaultSquareSizeUpperBound * share.ContinuationSparseShareContentSize
6 changes: 3 additions & 3 deletions pkg/da/data_availability_header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"testing"

"github.com/celestiaorg/celestia-app/v3/pkg/appconsts"
"github.com/celestiaorg/go-square/v2/share"
sh "github.com/celestiaorg/go-square/v2/share"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -245,7 +245,7 @@ func TestSquareSize(t *testing.T) {
// generateShares generates count number of shares with a constant namespace and
// share contents.
func generateShares(count int) (shares [][]byte) {
ns1 := share.MustNewV0Namespace(bytes.Repeat([]byte{1}, share.NamespaceVersionZeroIDSize))
ns1 := sh.MustNewV0Namespace(bytes.Repeat([]byte{1}, sh.NamespaceVersionZeroIDSize))

for i := 0; i < count; i++ {
share := generateShare(ns1.Bytes())
Expand All @@ -256,7 +256,7 @@ func generateShares(count int) (shares [][]byte) {
}

func generateShare(namespace []byte) (share []byte) {
remainder := bytes.Repeat([]byte{0xFF}, appconsts.ShareSize-len(namespace))
remainder := bytes.Repeat([]byte{0xFF}, sh.ShareSize-len(namespace))
share = append(share, namespace...)
share = append(share, remainder...)
return share
Expand Down
2 changes: 1 addition & 1 deletion pkg/inclusion/nmt_caching_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func chunkSlice(slice [][]byte, chunkSize int) [][][]byte {
// namespace.
func generateRandNamespacedRawData(count int) (result [][]byte) {
for i := 0; i < count; i++ {
rawData := tmrand.Bytes(appconsts.ShareSize)
rawData := tmrand.Bytes(share.ShareSize)
namespace := share.RandomBlobNamespace().Bytes()
copy(rawData, namespace)
result = append(result, rawData)
Expand Down
4 changes: 4 additions & 0 deletions pkg/user/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func (s *Signer) CreatePayForBlobs(accountName string, blobs []*share.Blob, opts
return nil, 0, fmt.Errorf("account %s not found", accountName)
}

if err := blobtypes.ValidateBlobs(blobs...); err != nil {
return nil, 0, err
}

msg, err := blobtypes.NewMsgPayForBlobs(acc.address.String(), s.appVersion, blobs...)
if err != nil {
return nil, 0, err
Expand Down
Loading
Loading