fix: app
Some checks failed
Continuous Integration (Commit) / lint (push) Has been cancelled

This commit is contained in:
MiniFrenchBread 2024-10-29 19:29:44 +08:00
parent e308e44dd6
commit 759d08a6eb
8 changed files with 331 additions and 22 deletions

View File

@ -110,6 +110,7 @@ import (
chainparams "github.com/0glabs/0g-chain/app/params" chainparams "github.com/0glabs/0g-chain/app/params"
"github.com/0glabs/0g-chain/chaincfg" "github.com/0glabs/0g-chain/chaincfg"
dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners" dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners"
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
"github.com/0glabs/0g-chain/x/bep3" "github.com/0glabs/0g-chain/x/bep3"
bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper" bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper"
@ -499,11 +500,18 @@ func NewApp(
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr) app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
// precopmiles // precopmiles
precompiles := make(map[common.Address]vm.PrecompiledContract) precompiles := make(map[common.Address]vm.PrecompiledContract)
// dasigners
daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper) daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper)
if err != nil { if err != nil {
panic("initialize precompile failed") panic(fmt.Sprintf("initialize dasigners precompile failed: %v", err))
} }
precompiles[daSignersPrecompile.Address()] = daSignersPrecompile precompiles[daSignersPrecompile.Address()] = daSignersPrecompile
// staking
stakingPrecompile, err := stakingprecompile.NewStakingPrecompile(app.stakingKeeper)
if err != nil {
panic(fmt.Sprintf("initialize staking precompile failed: %v", err))
}
precompiles[stakingPrecompile.Address()] = stakingPrecompile
app.evmKeeper = evmkeeper.NewKeeper( app.evmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],

View File

@ -14,6 +14,7 @@ import (
"github.com/0glabs/0g-chain/x/dasigners/v1/types" "github.com/0glabs/0g-chain/x/dasigners/v1/types"
abci "github.com/cometbft/cometbft/abci/types" abci "github.com/cometbft/cometbft/abci/types"
"github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -23,7 +24,6 @@ import (
"cosmossdk.io/math" "cosmossdk.io/math"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/evmos/ethermint/crypto/ethsecp256k1"
) )
type DASignersTestSuite struct { type DASignersTestSuite struct {
@ -44,8 +44,7 @@ func (suite *DASignersTestSuite) AddDelegation(from string, to string, amount ma
suite.Require().NoError(err) suite.Require().NoError(err)
validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr) validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr)
if !found { if !found {
consPriv, err := ethsecp256k1.GenerateKey() consPriv := ed25519.GenPrivKey()
suite.Require().NoError(err)
newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{}) newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
suite.Require().NoError(err) suite.Require().NoError(err)
validator = newValidator validator = newValidator

View File

@ -185,7 +185,7 @@ interface IStaking {
Description memory description, Description memory description,
CommissionRates memory commission, CommissionRates memory commission,
uint minSelfDelegation, uint minSelfDelegation,
string memory pubkey, string memory pubkey, // 0gchaind tendermint show-validator
uint value uint value
) external; ) external;

View File

@ -0,0 +1,65 @@
package staking_test
import (
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
sdk "github.com/cosmos/cosmos-sdk/types"
query "github.com/cosmos/cosmos-sdk/types/query"
)
func (s *StakingTestSuite) TestValidators() {
method := stakingprecompile.StakingFunctionValidators
testCases := []struct {
name string
malleate func() []byte
postCheck func(bz []byte)
gas uint64
expErr bool
errContains string
}{
{
"success",
func() []byte {
input, err := s.abi.Pack(
method,
"",
query.PageRequest{
Limit: 10,
CountTotal: true,
},
)
s.Assert().NoError(err)
return input
},
func(data []byte) {
out, err := s.abi.Methods[method].Outputs.Unpack(data)
s.Require().NoError(err, "failed to unpack output")
validators := out[0].([]stakingprecompile.Validator)
paginationResult := out[1].(stakingprecompile.PageResponse)
s.Assert().EqualValues(3, len(validators))
s.Assert().EqualValues(3, paginationResult.Total)
},
100000,
false,
"",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
s.SetupTest()
s.AddDelegation(s.signerOne.HexAddr, s.signerTwo.HexAddr, sdk.NewIntFromUint64(1000000))
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.errContains)
} else {
s.Require().NoError(err)
s.Require().NotNil(bz)
tc.postCheck(bz)
}
})
}
}

View File

@ -0,0 +1,102 @@
package staking_test
import (
"math/big"
"strings"
"testing"
"cosmossdk.io/math"
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
"github.com/0glabs/0g-chain/precompiles/testutil"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/stretchr/testify/suite"
)
type StakingTestSuite struct {
testutil.PrecompileTestSuite
abi abi.ABI
addr common.Address
staking *stakingprecompile.StakingPrecompile
stakingKeeper *stakingkeeper.Keeper
signerOne *testutil.TestSigner
signerTwo *testutil.TestSigner
}
func (suite *StakingTestSuite) SetupTest() {
suite.PrecompileTestSuite.SetupTest()
suite.stakingKeeper = suite.App.GetStakingKeeper()
suite.addr = common.HexToAddress(stakingprecompile.PrecompileAddress)
precompiles := suite.EvmKeeper.GetPrecompiles()
precompile, ok := precompiles[suite.addr]
suite.Assert().EqualValues(ok, true)
suite.staking = precompile.(*stakingprecompile.StakingPrecompile)
suite.signerOne = suite.GenSigner()
suite.signerTwo = suite.GenSigner()
abi, err := abi.JSON(strings.NewReader(stakingprecompile.StakingABI))
suite.Assert().NoError(err)
suite.abi = abi
}
func (suite *StakingTestSuite) AddDelegation(from string, to string, amount math.Int) {
accAddr, err := sdk.AccAddressFromHexUnsafe(from)
suite.Require().NoError(err)
valAddr, err := sdk.ValAddressFromHex(to)
suite.Require().NoError(err)
validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr)
if !found {
consPriv := ed25519.GenPrivKey()
newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
suite.Require().NoError(err)
validator = newValidator
}
validator.Tokens = validator.Tokens.Add(amount)
validator.DelegatorShares = validator.DelegatorShares.Add(amount.ToLegacyDec())
suite.StakingKeeper.SetValidator(suite.Ctx, validator)
bonded := suite.stakingKeeper.GetDelegatorBonded(suite.Ctx, accAddr)
suite.StakingKeeper.SetDelegation(suite.Ctx, stakingtypes.Delegation{
DelegatorAddress: accAddr.String(),
ValidatorAddress: valAddr.String(),
Shares: bonded.Add(amount).ToLegacyDec(),
})
}
func (suite *StakingTestSuite) runTx(input []byte, signer *testutil.TestSigner, gas uint64) ([]byte, error) {
contract := vm.NewPrecompile(vm.AccountRef(signer.Addr), vm.AccountRef(suite.addr), big.NewInt(0), gas)
contract.Input = input
msgEthereumTx := evmtypes.NewTx(suite.EvmKeeper.ChainID(), 0, &suite.addr, big.NewInt(0), gas, big.NewInt(0), big.NewInt(0), big.NewInt(0), input, nil)
msgEthereumTx.From = signer.HexAddr
err := msgEthereumTx.Sign(suite.EthSigner, signer.Signer)
suite.Assert().NoError(err, "failed to sign Ethereum message")
proposerAddress := suite.Ctx.BlockHeader().ProposerAddress
cfg, err := suite.EvmKeeper.EVMConfig(suite.Ctx, proposerAddress, suite.EvmKeeper.ChainID())
suite.Assert().NoError(err, "failed to instantiate EVM config")
msg, err := msgEthereumTx.AsMessage(suite.EthSigner, big.NewInt(0))
suite.Assert().NoError(err, "failed to instantiate Ethereum message")
evm := suite.EvmKeeper.NewEVM(suite.Ctx, msg, cfg, nil, suite.Statedb)
precompiles := suite.EvmKeeper.GetPrecompiles()
evm.WithPrecompiles(precompiles, []common.Address{suite.addr})
return suite.staking.Run(evm, contract, false)
}
func TestKeeperSuite(t *testing.T) {
suite.Run(t, new(StakingTestSuite))
}

View File

@ -0,0 +1,124 @@
package staking_test
import (
"encoding/base64"
"math/big"
"cosmossdk.io/math"
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
"github.com/ethereum/go-ethereum/common"
)
func (s *StakingTestSuite) TestCreateValidator() {
method := stakingprecompile.StakingFunctionCreateValidator
description := stakingprecompile.Description{
Moniker: "test node",
Identity: "test node identity",
Website: "http://test.node.com",
SecurityContact: "test node security contract",
Details: "test node details",
}
commission := stakingprecompile.CommissionRates{
Rate: math.LegacyOneDec().BigInt(),
MaxRate: math.LegacyOneDec().BigInt(),
MaxChangeRate: math.LegacyOneDec().BigInt(),
}
minSelfDelegation := big.NewInt(1)
pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g="
value := big.NewInt(100000000)
testCases := []struct {
name string
malleate func() []byte
gas uint64
callerAddress *common.Address
postCheck func(data []byte)
expError bool
errContains string
}{
{
"fail - ErrPubKeyInvalidLength",
func() []byte {
input, err := s.abi.Pack(
method,
description,
commission,
minSelfDelegation,
s.signerOne.HexAddr,
value,
)
s.Assert().NoError(err)
return input
},
200000,
nil,
func([]byte) {},
true,
stakingprecompile.ErrPubKeyInvalidLength,
},
{
"success",
func() []byte {
input, err := s.abi.Pack(
method,
description,
commission,
minSelfDelegation,
pubkey,
value,
)
s.Assert().NoError(err)
return input
},
200000,
nil,
func(data []byte) {},
false,
"",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
s.SetupTest()
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
if tc.expError {
s.Require().ErrorContains(err, tc.errContains)
s.Require().Empty(bz)
} else {
s.Require().NoError(err)
// query the validator in the staking keeper
validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr)
s.Require().NoError(err)
s.Require().NotNil(validator, "expected validator not to be nil")
tc.postCheck(bz)
isBonded := validator.IsBonded()
s.Require().Equal(false, isBonded, "expected validator bonded to be %t; got %t", false, isBonded)
consPubKey, err := validator.ConsPubKey()
s.Require().NoError(err)
consPubKeyBase64 := base64.StdEncoding.EncodeToString(consPubKey.Bytes())
s.Require().Equal(pubkey, consPubKeyBase64, "expected validator pubkey to be %s; got %s", pubkey, consPubKeyBase64)
operator := validator.GetOperator()
s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator)
commissionRate := validator.GetCommission()
s.Require().Equal(commission.Rate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", commission.Rate.String(), commissionRate.String())
valMinSelfDelegation := validator.GetMinSelfDelegation()
s.Require().Equal(minSelfDelegation.String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String())
moniker := validator.GetMoniker()
s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker)
jailed := validator.IsJailed()
s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed)
}
})
}
}

View File

@ -17,29 +17,29 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
type Commission struct { type Commission = struct {
CommissionRates CommissionRates `json:"commissionRates"` CommissionRates CommissionRates `json:"commissionRates"`
UpdateTime *big.Int `json:"updateTime"` UpdateTime *big.Int `json:"updateTime"`
} }
type CommissionRates struct { type CommissionRates = struct {
Rate *big.Int `json:"rate"` Rate *big.Int `json:"rate"`
MaxRate *big.Int `json:"maxRate"` MaxRate *big.Int `json:"maxRate"`
MaxChangeRate *big.Int `json:"maxChangeRate"` MaxChangeRate *big.Int `json:"maxChangeRate"`
} }
type Delegation struct { type Delegation = struct {
DelegatorAddress string `json:"delegatorAddress"` DelegatorAddress string `json:"delegatorAddress"`
ValidatorAddress string `json:"validatorAddress"` ValidatorAddress string `json:"validatorAddress"`
Shares *big.Int `json:"shares"` Shares *big.Int `json:"shares"`
} }
type DelegationResponse struct { type DelegationResponse = struct {
Delegation Delegation `json:"delegation"` Delegation Delegation `json:"delegation"`
Balance *big.Int `json:"balance"` Balance *big.Int `json:"balance"`
} }
type Description struct { type Description = struct {
Moniker string `json:"moniker"` Moniker string `json:"moniker"`
Identity string `json:"identity"` Identity string `json:"identity"`
Website string `json:"website"` Website string `json:"website"`
@ -47,12 +47,12 @@ type Description struct {
Details string `json:"details"` Details string `json:"details"`
} }
type NullableUint struct { type NullableUint = struct {
IsNull bool `json:"isNull"` IsNull bool `json:"isNull"`
Value *big.Int `json:"value"` Value *big.Int `json:"value"`
} }
type PageRequest struct { type PageRequest = struct {
Key []byte `json:"key"` Key []byte `json:"key"`
Offset uint64 `json:"offset"` Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"` Limit uint64 `json:"limit"`
@ -60,12 +60,12 @@ type PageRequest struct {
Reverse bool `json:"reverse"` Reverse bool `json:"reverse"`
} }
type PageResponse struct { type PageResponse = struct {
NextKey []byte `json:"nextKey"` NextKey []byte `json:"nextKey"`
Total uint64 `json:"total"` Total uint64 `json:"total"`
} }
type Params struct { type Params = struct {
UnbondingTime int64 `json:"unbondingTime"` UnbondingTime int64 `json:"unbondingTime"`
MaxValidators uint32 `json:"maxValidators"` MaxValidators uint32 `json:"maxValidators"`
MaxEntries uint32 `json:"maxEntries"` MaxEntries uint32 `json:"maxEntries"`
@ -74,14 +74,14 @@ type Params struct {
MinCommissionRate *big.Int `json:"minCommissionRate"` MinCommissionRate *big.Int `json:"minCommissionRate"`
} }
type Redelegation struct { type Redelegation = struct {
DelegatorAddress string `json:"delegatorAddress"` DelegatorAddress string `json:"delegatorAddress"`
ValidatorSrcAddress string `json:"validatorSrcAddress"` ValidatorSrcAddress string `json:"validatorSrcAddress"`
ValidatorDstAddress string `json:"validatorDstAddress"` ValidatorDstAddress string `json:"validatorDstAddress"`
Entries []RedelegationEntry `json:"entries"` Entries []RedelegationEntry `json:"entries"`
} }
type RedelegationEntry struct { type RedelegationEntry = struct {
CreationHeight int64 `json:"creationHeight"` CreationHeight int64 `json:"creationHeight"`
CompletionTime int64 `json:"completionTime"` CompletionTime int64 `json:"completionTime"`
InitialBalance *big.Int `json:"initialBalance"` InitialBalance *big.Int `json:"initialBalance"`
@ -90,23 +90,23 @@ type RedelegationEntry struct {
UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"` UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"`
} }
type RedelegationEntryResponse struct { type RedelegationEntryResponse = struct {
RedelegationEntry RedelegationEntry `json:"redelegationEntry"` RedelegationEntry RedelegationEntry `json:"redelegationEntry"`
Balance *big.Int `json:"balance"` Balance *big.Int `json:"balance"`
} }
type RedelegationResponse struct { type RedelegationResponse = struct {
Redelegation Redelegation `json:"redelegation"` Redelegation Redelegation `json:"redelegation"`
Entries []RedelegationEntryResponse `json:"entries"` Entries []RedelegationEntryResponse `json:"entries"`
} }
type UnbondingDelegation struct { type UnbondingDelegation = struct {
DelegatorAddress string `json:"delegatorAddress"` DelegatorAddress string `json:"delegatorAddress"`
ValidatorAddress string `json:"validatorAddress"` ValidatorAddress string `json:"validatorAddress"`
Entries []UnbondingDelegationEntry `json:"entries"` Entries []UnbondingDelegationEntry `json:"entries"`
} }
type UnbondingDelegationEntry struct { type UnbondingDelegationEntry = struct {
CreationHeight int64 `json:"creationHeight"` CreationHeight int64 `json:"creationHeight"`
CompletionTime int64 `json:"completionTime"` CompletionTime int64 `json:"completionTime"`
InitialBalance *big.Int `json:"initialBalance"` InitialBalance *big.Int `json:"initialBalance"`
@ -115,7 +115,7 @@ type UnbondingDelegationEntry struct {
UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"` UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"`
} }
type Validator struct { type Validator = struct {
OperatorAddress string `json:"operatorAddress"` OperatorAddress string `json:"operatorAddress"`
ConsensusPubkey string `json:"consensusPubkey"` ConsensusPubkey string `json:"consensusPubkey"`
Jailed bool `json:"jailed"` Jailed bool `json:"jailed"`

View File

@ -1,6 +1,7 @@
package testutil package testutil
import ( import (
"math/big"
"strings" "strings"
"github.com/0glabs/0g-chain/app" "github.com/0glabs/0g-chain/app"
@ -44,15 +45,25 @@ type TestSigner struct {
HexAddr string HexAddr string
PrivKey cryptotypes.PrivKey PrivKey cryptotypes.PrivKey
Signer keyring.Signer Signer keyring.Signer
ValAddr sdk.ValAddress
AccAddr sdk.AccAddress
} }
func GenSigner() *TestSigner { func (suite *PrecompileTestSuite) GenSigner() *TestSigner {
var s TestSigner var s TestSigner
addr, priv := emtests.NewAddrKey() addr, priv := emtests.NewAddrKey()
s.PrivKey = priv s.PrivKey = priv
s.Addr = addr s.Addr = addr
s.HexAddr = precopmiles_common.ToLowerHexWithoutPrefix(s.Addr) s.HexAddr = precopmiles_common.ToLowerHexWithoutPrefix(s.Addr)
s.Signer = emtests.NewSigner(priv) s.Signer = emtests.NewSigner(priv)
valAddr, _ := sdk.ValAddressFromHex(s.HexAddr)
accAddr, _ := sdk.AccAddressFromHexUnsafe(s.HexAddr)
s.ValAddr = valAddr
s.AccAddr = accAddr
// 10000 a0gi for test
suite.App.GetBankKeeper().MintCoins(suite.Ctx, "mint", sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000))))
suite.App.GetBankKeeper().SendCoinsFromModuleToAccount(suite.Ctx, "mint", accAddr, sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000))))
return &s return &s
} }