Skip to content

Commit

Permalink
feat!(state/core_access): add TxConfig (#3349)
Browse files Browse the repository at this point in the history
List of breaking changes:

Added a TxConfig struct that is applied to all write transactions(transfer/submitPFB etc);
Renamed KeyringAccName to DefaultKeyName and KeyringBackend to DefaultBackendName in the config;
Removed blob.GasPrice since blob.Submit requires SubmitOptions which are type alias of TxConfig;
Reworked flags for tx submission through CLI;
Added state.Blob which is an alias for app.Blob(State Module now requires blob type from app)(Was added to avoid circular dependency between node's blob Module and node's state Module);
  • Loading branch information
vgonkivs authored Jul 4, 2024
1 parent 7c86795 commit 3d26a1a
Show file tree
Hide file tree
Showing 30 changed files with 864 additions and 637 deletions.
11 changes: 9 additions & 2 deletions api/docgen/examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ var ExampleValues = map[reflect.Type]interface{}{
reflect.TypeOf(42): 42,
reflect.TypeOf(byte(7)): byte(7),
reflect.TypeOf(float64(42)): float64(42),
reflect.TypeOf(blob.GasPrice(0)): blob.GasPrice(0.002),
reflect.TypeOf(true): true,
reflect.TypeOf([]byte{}): []byte("byte array"),
reflect.TypeOf(node.Full): node.Full,
Expand Down Expand Up @@ -177,8 +176,16 @@ func init() {
if err != nil {
panic(err)
}

addToExampleValues(libhead.Hash(hash))

txConfig := state.NewTxConfig(
state.WithGasPrice(0.002),
state.WithGas(142225),
state.WithKeyName("my_celes_key"),
state.WithSignerAddress("celestia1pjcmwj8w6hyr2c4wehakc5g8cfs36aysgucx66"),
state.WithFeeGranterAddress("celestia1hakc56ax66ypjcmwj8w6hyr2c4g8cfs3wesguc"),
)
addToExampleValues(txConfig)
}

func addToExampleValues(v interface{}) {
Expand Down
6 changes: 3 additions & 3 deletions api/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,14 @@ func TestAuthedRPC(t *testing.T) {
expectedResp := &state.TxResponse{}
if tt.perm > 2 {
server.State.EXPECT().Delegate(gomock.Any(), gomock.Any(),
gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedResp, nil)
gomock.Any(), gomock.Any()).Return(expectedResp, nil)
txResp, err := rpcClient.State.Delegate(ctx,
state.ValAddress{}, state.Int{}, state.Int{}, 0)
state.ValAddress{}, state.Int{}, state.NewTxConfig())
require.NoError(t, err)
require.Equal(t, expectedResp, txResp)
} else {
_, err := rpcClient.State.Delegate(ctx,
state.ValAddress{}, state.Int{}, state.Int{}, 0)
state.ValAddress{}, state.Int{}, state.NewTxConfig())
require.Error(t, err)
require.ErrorContains(t, err, "missing permission")
}
Expand Down
10 changes: 10 additions & 0 deletions blob/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/tendermint/tendermint/types"

"github.com/celestiaorg/celestia-app/pkg/shares"
apptypes "github.com/celestiaorg/celestia-app/x/blob/types"

"github.com/celestiaorg/celestia-node/share"
)
Expand Down Expand Up @@ -36,6 +37,15 @@ func BlobsToShares(blobs ...*Blob) ([]share.Share, error) {
return shares.ToBytes(rawShares), nil
}

// ToAppBlobs converts node's blob type to the blob type from celestia-app.
func ToAppBlobs(blobs ...*Blob) []*apptypes.Blob {
appBlobs := make([]*apptypes.Blob, 0, len(blobs))
for i := range blobs {
appBlobs[i] = &blobs[i].Blob
}
return appBlobs
}

// toAppShares converts node's raw shares to the app shares, skipping padding
func toAppShares(shrs ...share.Share) ([]shares.Share, error) {
appShrs := make([]shares.Share, 0, len(shrs))
Expand Down
51 changes: 12 additions & 39 deletions blob/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,22 @@ import (
"context"
"errors"
"fmt"
"math"
"slices"
"sync"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/types"
auth "github.com/cosmos/cosmos-sdk/x/auth/types"
logging "github.com/ipfs/go-log/v2"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"

"github.com/celestiaorg/celestia-app/pkg/appconsts"
"github.com/celestiaorg/celestia-app/pkg/shares"
blobtypes "github.com/celestiaorg/celestia-app/x/blob/types"

"github.com/celestiaorg/celestia-node/header"
"github.com/celestiaorg/celestia-node/libs/utils"
"github.com/celestiaorg/celestia-node/share"
"github.com/celestiaorg/celestia-node/state"
)

var (
Expand All @@ -34,21 +30,15 @@ var (
tracer = otel.Tracer("blob/service")
)

// GasPrice represents the amount to be paid per gas unit. Fee is set by
// multiplying GasPrice by GasLimit, which is determined by the blob sizes.
type GasPrice float64

// DefaultGasPrice returns the default gas price, letting node automatically
// determine the Fee based on the passed blob sizes.
func DefaultGasPrice() GasPrice {
return -1.0
}
// SubmitOptions aliases TxOptions from state package allowing users
// to specify options for SubmitPFB transaction.
type SubmitOptions = state.TxConfig

// Submitter is an interface that allows submitting blobs to the celestia-core. It is used to
// avoid a circular dependency between the blob and the state package, since the state package needs
// the blob.Blob type for this signature.
type Submitter interface {
SubmitPayForBlob(ctx context.Context, fee sdkmath.Int, gasLim uint64, blobs []*Blob) (*types.TxResponse, error)
SubmitPayForBlob(context.Context, []*state.Blob, *state.TxConfig) (*types.TxResponse, error)
}

type Service struct {
Expand All @@ -72,39 +62,22 @@ func NewService(
}
}

// SubmitOptions contains the information about fee and gasLimit price in order to configure the
// Submit request.
type SubmitOptions struct {
Fee int64
GasLimit uint64
}

// DefaultSubmitOptions creates a default fee and gas price values.
func DefaultSubmitOptions() *SubmitOptions {
return &SubmitOptions{
Fee: -1,
GasLimit: 0,
}
}

// Submit sends PFB transaction and reports the height at which it was included.
// Allows sending multiple Blobs atomically synchronously.
// Uses default wallet registered on the Node.
// Handles gas estimation and fee calculation.
func (s *Service) Submit(ctx context.Context, blobs []*Blob, gasPrice GasPrice) (uint64, error) {
func (s *Service) Submit(ctx context.Context, blobs []*Blob, txConfig *SubmitOptions) (uint64, error) {
log.Debugw("submitting blobs", "amount", len(blobs))

options := DefaultSubmitOptions()
if gasPrice >= 0 {
blobSizes := make([]uint32, len(blobs))
for i, blob := range blobs {
blobSizes[i] = uint32(len(blob.Data))
appblobs := make([]*state.Blob, len(blobs))
for i := range blobs {
if err := blobs[i].Namespace().ValidateForBlob(); err != nil {
return 0, err
}
options.GasLimit = blobtypes.EstimateGas(blobSizes, appconsts.DefaultGasPerBlobByte, auth.DefaultTxSizeCostPerByte)
options.Fee = types.NewInt(int64(math.Ceil(float64(gasPrice) * float64(options.GasLimit)))).Int64()
appblobs[i] = &blobs[i].Blob
}

resp, err := s.blobSubmitter.SubmitPayForBlob(ctx, types.NewInt(options.Fee), options.GasLimit, blobs)
resp, err := s.blobSubmitter.SubmitPayForBlob(ctx, appblobs, txConfig)
if err != nil {
return 0, err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Options passed on start override configuration options only on start and are not
// TODO @renaynay: Include option for setting custom `userInput` parameter with
// implementation of https://github.com/celestiaorg/celestia-node/issues/415.
encConf := encoding.MakeConfig(app.ModuleEncodingRegisters...)
ring, err := keyring.New(app.Name, cfg.State.KeyringBackend, keysPath, os.Stdin, encConf.Codec)
ring, err := keyring.New(app.Name, cfg.State.DefaultBackendName, keysPath, os.Stdin, encConf.Codec)
if err != nil {
return err
}
Expand Down
6 changes: 1 addition & 5 deletions cmd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,7 @@ func PersistentPreRunEnv(cmd *cobra.Command, nodeType node.Type, _ []string) err
return err
}

err = state.ParseFlags(cmd, &cfg.State)
if err != nil {
return err
}

state.ParseFlags(cmd, &cfg.State)
rpc_cfg.ParseFlags(cmd, &cfg.RPC)
gateway.ParseFlags(cmd, &cfg.Gateway)

Expand Down
29 changes: 11 additions & 18 deletions docs/adr/adr-009-public-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,15 @@ NetworkHead(ctx context.Context) (*header.ExtendedHeader, error)
ctx context.Context,
nID namespace.ID,
data []byte,
fee types.Int,
gasLimit uint64,
config *state.TxConfig,
) (*state.TxResponse, error)
// Transfer sends the given amount of coins from default wallet of the node
// to the given account address.
Transfer(
ctx context.Context,
to types.Address,
amount types.Int,
fee types.Int,
gasLimit uint64,
config *state.TxConfig,
) (*state.TxResponse, error)

// StateModule also provides StakingModule
Expand All @@ -284,26 +282,23 @@ yet.
ctx context.Context,
delAddr state.ValAddress,
amount state.Int,
fee types.Int,
gasLim uint64,
config *state.TxConfig,
) (*state.TxResponse, error)
// BeginRedelegate sends a user's delegated tokens to a new validator for redelegation.
BeginRedelegate(
ctx context.Context,
srcValAddr,
dstValAddr state.ValAddress,
amount state.Int,
fee types.Int,
gasLim uint64,
config *state.TxConfig,
) (*state.TxResponse, error)
// Undelegate undelegates a user's delegated tokens, unbonding them from the
// current validator.
Undelegate(
ctx context.Context,
delAddr state.ValAddress,
amount state.Int,
fee types.Int,
gasLim uint64,
config *state.TxConfig,
) (*state.TxResponse, error)

// CancelUnbondingDelegation cancels a user's pending undelegation from a
Expand All @@ -313,8 +308,7 @@ yet.
valAddr state.ValAddress,
amount types.Int,
height types.Int,
fee types.Int,
gasLim uint64,
config *state.TxConfig,
) (*state.TxResponse, error)

// QueryDelegation retrieves the delegation information between a delegator
Expand Down Expand Up @@ -404,17 +398,16 @@ type BankModule interface {
// SubmitPayForBlob builds, signs and submits a PayForBlob transaction.
SubmitPayForBlob(
ctx context.Context,
nID namespace.ID,
data []byte,
gasLimit uint64,
blobs []*state.Blob,
config *state.TxConfig,
) (*state.TxResponse, error)
// Transfer sends the given amount of coins from default wallet of the node
// to the given account address.
Transfer(
ctx context.Context,
to types.Address,
amount types.Int,
gasLimit uint64,
to state.AccAddress,
amount state.Int,
config *state.TxConfig,
) (*state.TxResponse, error)
}
```
Expand Down
8 changes: 4 additions & 4 deletions nodebuilder/blob/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Module interface {
// Submit sends Blobs and reports the height in which they were included.
// Allows sending multiple Blobs atomically synchronously.
// Uses default wallet registered on the Node.
Submit(_ context.Context, _ []*blob.Blob, _ blob.GasPrice) (height uint64, _ error)
Submit(_ context.Context, _ []*blob.Blob, _ *blob.SubmitOptions) (height uint64, _ error)
// Get retrieves the blob by commitment under the given namespace and height.
Get(_ context.Context, height uint64, _ share.Namespace, _ blob.Commitment) (*blob.Blob, error)
// GetAll returns all blobs under the given namespaces at the given height.
Expand All @@ -38,16 +38,16 @@ type Module interface {

type API struct {
Internal struct {
Submit func(context.Context, []*blob.Blob, blob.GasPrice) (uint64, error) `perm:"write"`
Submit func(context.Context, []*blob.Blob, *blob.SubmitOptions) (uint64, error) `perm:"write"`
Get func(context.Context, uint64, share.Namespace, blob.Commitment) (*blob.Blob, error) `perm:"read"`
GetAll func(context.Context, uint64, []share.Namespace) ([]*blob.Blob, error) `perm:"read"`
GetProof func(context.Context, uint64, share.Namespace, blob.Commitment) (*blob.Proof, error) `perm:"read"`
Included func(context.Context, uint64, share.Namespace, *blob.Proof, blob.Commitment) (bool, error) `perm:"read"`
}
}

func (api *API) Submit(ctx context.Context, blobs []*blob.Blob, gasPrice blob.GasPrice) (uint64, error) {
return api.Internal.Submit(ctx, blobs, gasPrice)
func (api *API) Submit(ctx context.Context, blobs []*blob.Blob, options *blob.SubmitOptions) (uint64, error) {
return api.Internal.Submit(ctx, blobs, options)
}

func (api *API) Get(
Expand Down
25 changes: 9 additions & 16 deletions nodebuilder/blob/cmd/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ import (

"github.com/celestiaorg/celestia-node/blob"
cmdnode "github.com/celestiaorg/celestia-node/cmd"
state "github.com/celestiaorg/celestia-node/nodebuilder/state/cmd"
"github.com/celestiaorg/celestia-node/share"
)

var (
base64Flag bool

gasPrice float64

// flagFileInput allows the user to provide file path to the json file
// for submitting multiple blobs.
flagFileInput = "input-file"
Expand All @@ -33,25 +32,19 @@ func init() {
&base64Flag,
"base64",
false,
"printed blob's data and namespace as base64 strings",
"Printed blob's data and namespace as base64 strings",
)

getAllCmd.PersistentFlags().BoolVar(
&base64Flag,
"base64",
false,
"printed blob's data and namespace as base64 strings",
"Printed blob's data and namespace as base64 strings",
)

submitCmd.PersistentFlags().Float64Var(
&gasPrice,
"gas.price",
float64(blob.DefaultGasPrice()),
"specifies gas price (in utia) for blob submission.\n"+
"Gas price will be set to default (0.002) if no value is passed",
)
state.ApplyFlags(submitCmd)

submitCmd.PersistentFlags().String(flagFileInput, "", "Specify the file input")
submitCmd.PersistentFlags().String(flagFileInput, "", "Specifies the file input")
}

var Cmd = &cobra.Command{
Expand Down Expand Up @@ -200,21 +193,21 @@ var submitCmd = &cobra.Command{
jsonBlobs = append(jsonBlobs, blobJSON{Namespace: args[0], BlobData: args[1]})
}

var blobs []*blob.Blob
var resultBlobs []*blob.Blob
var commitments []blob.Commitment
for _, jsonBlob := range jsonBlobs {
blob, err := getBlobFromArguments(jsonBlob.Namespace, jsonBlob.BlobData)
if err != nil {
return err
}
blobs = append(blobs, blob)
resultBlobs = append(resultBlobs, blob)
commitments = append(commitments, blob.Commitment)
}

height, err := client.Blob.Submit(
cmd.Context(),
blobs,
blob.GasPrice(gasPrice),
resultBlobs,
state.GetTxConfig(),
)

response := struct {
Expand Down
3 changes: 2 additions & 1 deletion nodebuilder/blob/mocks/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3d26a1a

Please sign in to comment.