Skip to content

Commit

Permalink
Merge branch 'main' into chore/return-v1
Browse files Browse the repository at this point in the history
aljo242 authored Jan 31, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents a58622d + 009bcc3 commit d1c33cd
Showing 13 changed files with 328 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-update-all.yml
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ jobs:
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: Generate Token
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1
uses: actions/create-github-app-token@136412a57a7081aa63c935a2cc2918f76c34f514 # v1
id: app-token
with:
app-id: "${{ secrets.APP_ID }}"
13 changes: 12 additions & 1 deletion docs/user/run-node/00-keyring.md
Original file line number Diff line number Diff line change
@@ -29,12 +29,14 @@ is a list of the most popular operating systems and their respective passwords m
* GNU/Linux:
* [libsecret](https://gitlab.gnome.org/GNOME/libsecret)
* [kwallet](https://api.kde.org/frameworks/kwallet/html/index.html)
* [keyctl](https://www.kernel.org/doc/html/latest/security/keys/core.html)

GNU/Linux distributions that use GNOME as default desktop environment typically come with
[Seahorse](https://wiki.gnome.org/Apps/Seahorse). Users of KDE based distributions are
commonly provided with [KDE Wallet Manager](https://userbase.kde.org/KDE_Wallet_Manager).
Whilst the former is in fact a `libsecret` convenient frontend, the latter is a `kwallet`
client.
client. `keyctl` is a secure backend leverages the Linux's kernel security key management system
to store cryptographic keys securely in memory.

`os` is the default option since operating system's default credentials managers are
designed to meet users' most common needs and provide them with a comfortable
@@ -93,6 +95,15 @@ GNU/Linux distributions that ships KDE as default desktop environment. Please re
[KWallet Handbook](https://docs.kde.org/stable5/en/kwalletmanager/kwallet5/index.html) for more
information.

### The `keyctl` backend

The *Kernel Key Retention Service* is a security facility that
has been added to the Linux kernel relatively recently. It allows sensitive
cryptographic data such as passwords, private key, authentication tokens, etc
to be stored securely in memory.

The `keyctl` backend is available on Linux platforms only.

### The `test` backend

The `test` backend is a password-less variation of the `file` backend. Keys are stored
9 changes: 9 additions & 0 deletions server/v2/api/swagger/server.go
Original file line number Diff line number Diff line change
@@ -64,6 +64,15 @@ func New[T transaction.Tx](
return s, nil
}

// NewWithConfigOptions creates a new telemetry server with the provided config options.
// It is *not* a fully functional server (since it has been created without dependencies)
// The returned server should only be used to get and set configuration.
func NewWithConfigOptions[T transaction.Tx](opts ...CfgOption) *Server[T] {
return &Server[T]{
cfgOptions: opts,
}
}

// Name returns the server's name
func (s *Server[T]) Name() string {
return ServerName
11 changes: 10 additions & 1 deletion simapp/v2/simdv2/cmd/testnet.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ import (
"cosmossdk.io/server/v2/api/grpc"
"cosmossdk.io/server/v2/api/grpcgateway"
"cosmossdk.io/server/v2/api/rest"
"cosmossdk.io/server/v2/api/swagger"
"cosmossdk.io/server/v2/api/telemetry"
"cosmossdk.io/server/v2/cometbft"
"cosmossdk.io/server/v2/store"
@@ -188,6 +189,7 @@ func initTestnetFiles[T transaction.Tx](
grpcPort = 9090
restPort = 8080
telemetryPort = 7180
swaggerPort = 8090
)
p2pPortStart := 26656

@@ -199,6 +201,7 @@ func initTestnetFiles[T transaction.Tx](
grpcgatewayConfig := grpcgateway.DefaultConfig()
restConfig := rest.DefaultConfig()
telemetryConfig := telemetry.DefaultConfig()
swaggerConfig := swagger.DefaultConfig()

if args.singleMachine {
portOffset = i
@@ -228,6 +231,11 @@ func initTestnetFiles[T transaction.Tx](
Enable: true,
Address: fmt.Sprintf("127.0.0.1:%d", telemetryPort+portOffset),
}

swaggerConfig = &swagger.Config{
Enable: true,
Address: fmt.Sprintf("127.0.0.1:%d", swaggerPort+portOffset),
}
}

nodeDirName := fmt.Sprintf("%s%d", args.nodeDirPrefix, i)
@@ -364,7 +372,8 @@ func initTestnetFiles[T transaction.Tx](
grpcgatewayServer := grpcgateway.NewWithConfigOptions[T](grpcgateway.OverwriteDefaultConfig(grpcgatewayConfig))
restServer := rest.NewWithConfigOptions[T](rest.OverwriteDefaultConfig(restConfig))
telemetryServer := telemetry.NewWithConfigOptions[T](telemetry.OverwriteDefaultConfig(telemetryConfig))
server := serverv2.NewServer[T](serverCfg, cometServer, storeServer, grpcServer, grpcgatewayServer, restServer, telemetryServer)
swaggerServer := swagger.NewWithConfigOptions[T](swagger.OverwriteDefaultConfig(swaggerConfig))
server := serverv2.NewServer[T](serverCfg, cometServer, storeServer, grpcServer, grpcgatewayServer, restServer, telemetryServer, swaggerServer)
err = server.WriteConfig(filepath.Join(nodeDir, "config"))
if err != nil {
return err
17 changes: 17 additions & 0 deletions types/mempool/mempool_test.go
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import (
"fmt"
"math/rand"
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
@@ -55,6 +56,21 @@ type testTx struct {
address sdk.AccAddress
// useful for debugging
strAddress string
unordered bool
timeout *time.Time
}

// GetTimeoutTimeStamp implements types.TxWithUnordered.
func (tx testTx) GetTimeoutTimeStamp() time.Time {
if tx.timeout == nil {
return time.Time{}
}
return *tx.timeout
}

// GetUnordered implements types.TxWithUnordered.
func (tx testTx) GetUnordered() bool {
return tx.unordered
}

func (tx testTx) GetSigners() ([][]byte, error) { panic("not implemented") }
@@ -73,6 +89,7 @@ func (tx testTx) GetSignaturesV2() (res []txsigning.SignatureV2, err error) {

var (
_ sdk.Tx = (*testTx)(nil)
_ sdk.TxWithUnordered = (*testTx)(nil)
_ signing.SigVerifiableTx = (*testTx)(nil)
_ cryptotypes.PubKey = (*testPubKey)(nil)
)
20 changes: 10 additions & 10 deletions types/mempool/priority_nonce.go
Original file line number Diff line number Diff line change
@@ -224,13 +224,13 @@ func (mp *PriorityNonceMempool[C]) Insert(ctx context.Context, tx sdk.Tx) error
priority := mp.cfg.TxPriority.GetTxPriority(ctx, tx)
nonce := sig.Sequence

// if it's an unordered tx, we use the gas instead of the nonce
// if it's an unordered tx, we use the timeout timestamp instead of the nonce
if unordered, ok := tx.(sdk.TxWithUnordered); ok && unordered.GetUnordered() {
gasLimit, err := unordered.GetGasLimit()
nonce = gasLimit
if err != nil {
return err
timestamp := unordered.GetTimeoutTimeStamp().Unix()
if timestamp < 0 {
return errors.New("invalid timestamp value")
}
nonce = uint64(timestamp)
}

key := txMeta[C]{nonce: nonce, priority: priority, sender: sender}
@@ -469,13 +469,13 @@ func (mp *PriorityNonceMempool[C]) Remove(tx sdk.Tx) error {
sender := sig.Signer.String()
nonce := sig.Sequence

// if it's an unordered tx, we use the gas instead of the nonce
// if it's an unordered tx, we use the timeout timestamp instead of the nonce
if unordered, ok := tx.(sdk.TxWithUnordered); ok && unordered.GetUnordered() {
gasLimit, err := unordered.GetGasLimit()
nonce = gasLimit
if err != nil {
return err
timestamp := unordered.GetTimeoutTimeStamp().Unix()
if timestamp < 0 {
return errors.New("invalid timestamp value")
}
nonce = uint64(timestamp)
}

scoreKey := txMeta[C]{nonce: nonce, sender: sender}
37 changes: 37 additions & 0 deletions types/mempool/priority_nonce_test.go
Original file line number Diff line number Diff line change
@@ -970,3 +970,40 @@ func TestNextSenderTx_TxReplacement(t *testing.T) {
iter := mp.Select(ctx, nil)
require.Equal(t, txs[3], iter.Tx())
}

func TestPriorityNonceMempool_UnorderedTx(t *testing.T) {
ctx := sdk.NewContext(nil, false, log.NewNopLogger())
accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 2)
sa := accounts[0].Address
sb := accounts[1].Address

mp := mempool.DefaultPriorityMempool()

now := time.Now()
oneHour := now.Add(1 * time.Hour)
thirtyMin := now.Add(30 * time.Minute)
twoHours := now.Add(2 * time.Hour)
fifteenMin := now.Add(15 * time.Minute)

txs := []testTx{
{id: 1, priority: 0, address: sa, timeout: &thirtyMin, unordered: true},
{id: 0, priority: 0, address: sa, timeout: &oneHour, unordered: true},
{id: 3, priority: 0, address: sb, timeout: &fifteenMin, unordered: true},
{id: 2, priority: 0, address: sb, timeout: &twoHours, unordered: true},
}

for _, tx := range txs {
c := ctx.WithPriority(tx.priority)
require.NoError(t, mp.Insert(c, tx))
}

require.Equal(t, 4, mp.CountTx())

orderedTxs := fetchTxs(mp.Select(ctx, nil), 100000)
require.Equal(t, len(txs), len(orderedTxs))

// check order
for i, tx := range orderedTxs {
require.Equal(t, txs[i].id, tx.(testTx).id)
}
}
28 changes: 14 additions & 14 deletions types/mempool/sender_nonce.go
Original file line number Diff line number Diff line change
@@ -139,21 +139,21 @@ func (snm *SenderNonceMempool) Insert(_ context.Context, tx sdk.Tx) error {
sender := sdk.AccAddress(sig.PubKey.Address()).String()
nonce := sig.Sequence

// if it's an unordered tx, we use the timeout timestamp instead of the nonce
if unordered, ok := tx.(sdk.TxWithUnordered); ok && unordered.GetUnordered() {
timestamp := unordered.GetTimeoutTimeStamp().Unix()
if timestamp < 0 {
return errors.New("invalid timestamp value")
}
nonce = uint64(timestamp)
}

senderTxs, found := snm.senders[sender]
if !found {
senderTxs = skiplist.New(skiplist.Uint64)
snm.senders[sender] = senderTxs
}

// if it's an unordered tx, we use the gas instead of the nonce
if unordered, ok := tx.(sdk.TxWithUnordered); ok && unordered.GetUnordered() {
gasLimit, err := unordered.GetGasLimit()
nonce = gasLimit
if err != nil {
return err
}
}

senderTxs.Set(nonce, tx)

key := txKey{nonce: nonce, address: sender}
@@ -236,13 +236,13 @@ func (snm *SenderNonceMempool) Remove(tx sdk.Tx) error {
sender := sdk.AccAddress(sig.PubKey.Address()).String()
nonce := sig.Sequence

// if it's an unordered tx, we use the gas instead of the nonce
// if it's an unordered tx, we use the timeout timestamp instead of the nonce
if unordered, ok := tx.(sdk.TxWithUnordered); ok && unordered.GetUnordered() {
gasLimit, err := unordered.GetGasLimit()
nonce = gasLimit
if err != nil {
return err
timestamp := unordered.GetTimeoutTimeStamp().Unix()
if timestamp < 0 {
return errors.New("invalid timestamp value")
}
nonce = uint64(timestamp)
}

senderTxs, found := snm.senders[sender]
65 changes: 65 additions & 0 deletions types/mempool/sender_nonce_test.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import (
"fmt"
"math/rand"
"testing"
"time"

"github.com/stretchr/testify/require"

@@ -192,3 +193,67 @@ func (s *MempoolTestSuite) TestTxNotFoundOnSender() {
err = mp.Remove(tx)
require.Equal(t, mempool.ErrTxNotFound, err)
}

func (s *MempoolTestSuite) TestUnorderedTx() {
t := s.T()

ctx := sdk.NewContext(nil, false, log.NewNopLogger())
accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 2)
sa := accounts[0].Address
sb := accounts[1].Address

mp := mempool.NewSenderNonceMempool(mempool.SenderNonceMaxTxOpt(5000))

now := time.Now()
oneHour := now.Add(1 * time.Hour)
thirtyMin := now.Add(30 * time.Minute)
twoHours := now.Add(2 * time.Hour)
fifteenMin := now.Add(15 * time.Minute)

txs := []testTx{
{id: 0, address: sa, timeout: &oneHour, unordered: true},
{id: 1, address: sa, timeout: &thirtyMin, unordered: true},
{id: 2, address: sb, timeout: &twoHours, unordered: true},
{id: 3, address: sb, timeout: &fifteenMin, unordered: true},
}

for _, tx := range txs {
c := ctx.WithPriority(tx.priority)
require.NoError(t, mp.Insert(c, tx))
}

require.Equal(t, 4, mp.CountTx())

orderedTxs := fetchTxs(mp.Select(ctx, nil), 100000)
require.Equal(t, len(txs), len(orderedTxs))

// Because the sender is selected randomly it can be any of these options
acceptableOptions := [][]int{
{3, 1, 2, 0},
{3, 1, 0, 2},
{3, 2, 1, 0},
{1, 3, 0, 2},
{1, 3, 2, 0},
{1, 0, 3, 2},
}

orderedTxsIds := make([]int, len(orderedTxs))
for i, tx := range orderedTxs {
orderedTxsIds[i] = tx.(testTx).id
}

anyAcceptableOrder := false
for _, option := range acceptableOptions {
for i, tx := range orderedTxs {
if tx.(testTx).id != txs[option[i]].id {
break
}

if i == len(orderedTxs)-1 {
anyAcceptableOrder = true
}
}
}

require.True(t, anyAcceptableOrder, "expected any of %v but got %v", acceptableOptions, orderedTxsIds)
}
32 changes: 32 additions & 0 deletions x/auth/ante/ante_test.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
"fmt"
"strings"
"testing"
"time"

"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
@@ -1384,3 +1385,34 @@ func TestAnteHandlerReCheck(t *testing.T) {
_, err = suite.anteHandler(suite.ctx, tx, false)
require.NotNil(t, err, "antehandler on recheck did not fail once feePayer no longer has sufficient funds")
}

func TestAnteHandlerUnorderedTx(t *testing.T) {
suite := SetupTestSuite(t, false)
accs := suite.CreateTestAccounts(1)
msg := testdata.NewTestMsg(accs[0].acc.GetAddress())

// First send a normal sequential tx with sequence 0
suite.bankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), accs[0].acc.GetAddress(), authtypes.FeeCollectorName, testdata.NewTestFeeAmount()).Return(nil).AnyTimes()

privs, accNums, accSeqs := []cryptotypes.PrivKey{accs[0].priv}, []uint64{1000}, []uint64{0}
_, err := suite.DeliverMsgs(t, privs, []sdk.Msg{msg}, testdata.NewTestFeeAmount(), testdata.NewTestGasLimit(), accNums, accSeqs, suite.ctx.ChainID(), false)
require.NoError(t, err)

// we try to send another tx with the same sequence, it will fail
_, err = suite.DeliverMsgs(t, privs, []sdk.Msg{msg}, testdata.NewTestFeeAmount(), testdata.NewTestGasLimit(), accNums, accSeqs, suite.ctx.ChainID(), false)
require.Error(t, err)

// now we'll still use the same sequence but because it's unordered, it will be ignored and accepted anyway
msgs := []sdk.Msg{msg}
require.NoError(t, suite.txBuilder.SetMsgs(msgs...))
suite.txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit())

tx, txErr := suite.CreateTestUnorderedTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), apisigning.SignMode_SIGN_MODE_DIRECT, true, time.Now().Add(time.Minute))
require.NoError(t, txErr)
txBytes, err := suite.clientCtx.TxConfig.TxEncoder()(tx)
bytesCtx := suite.ctx.WithTxBytes(txBytes)
require.NoError(t, err)
_, err = suite.anteHandler(bytesCtx, tx, false)
require.NoError(t, err)
}
Loading

0 comments on commit d1c33cd

Please sign in to comment.