Skip to content

Commit

Permalink
Merge branch 'master' into fuzz-BasicLitExpr
Browse files Browse the repository at this point in the history
  • Loading branch information
n2p5 authored Jan 10, 2025
2 parents 1e50af3 + 1b89166 commit 5a27a5e
Show file tree
Hide file tree
Showing 18 changed files with 210 additions and 115 deletions.
1 change: 0 additions & 1 deletion contribs/gnogenesis/internal/txs/txs_add_packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (

const (
defaultAccount_Name = "test1"
defaultAccount_Address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
defaultAccount_Seed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast"
defaultAccount_publicKey = "gpub1pgfj7ard9eg82cjtv4u4xetrwqer2dntxyfzxz3pq0skzdkmzu0r9h6gny6eg8c9dc303xrrudee6z4he4y7cs5rnjwmyf40yaj"
)
Expand Down
104 changes: 76 additions & 28 deletions gno.land/cmd/gnoland/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,20 @@ var startGraphic = strings.ReplaceAll(`
/___/
`, "'", "`")

var (
// Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go
genesisDeployAddress = crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // test1
genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000)))
)
// Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go
var genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000)))

type startCfg struct {
gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisBalancesFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisTxsFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisRemote string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisFile string
chainID string
dataDir string
lazyInit bool
gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
skipGenesisSigVerification bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisBalancesFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisTxsFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisRemote string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
genesisFile string
chainID string
dataDir string
lazyInit bool

logLevel string
logFormat string
Expand All @@ -86,7 +84,6 @@ func newStartCmd(io commands.IO) *commands.Command {
func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
gnoroot := gnoenv.RootDir()
defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.jsonl")

fs.BoolVar(
&c.skipFailingGenesisTxs,
Expand All @@ -95,6 +92,13 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
"don't panic when replaying invalid genesis txs",
)

fs.BoolVar(
&c.skipGenesisSigVerification,
"skip-genesis-sig-verification",
false,
"don't panic when replaying invalidly signed genesis txs",
)

fs.StringVar(
&c.genesisBalancesFile,
"genesis-balances-file",
Expand All @@ -105,7 +109,7 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
fs.StringVar(
&c.genesisTxsFile,
"genesis-txs-file",
defaultGenesisTxsFile,
"",
"initial txs to replay",
)

Expand Down Expand Up @@ -218,7 +222,7 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error {
)

// Init a new genesis.json
if err := lazyInitGenesis(io, c, genesisPath, privateKey.GetPubKey()); err != nil {
if err := lazyInitGenesis(io, c, genesisPath, privateKey.Key.PrivKey); err != nil {
return fmt.Errorf("unable to initialize genesis.json, %w", err)
}
}
Expand All @@ -238,7 +242,16 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error {
minGasPrices := cfg.Application.MinGasPrices

// Create application and node
cfg.LocalApp, err = gnoland.NewApp(nodeDir, c.skipFailingGenesisTxs, evsw, logger, minGasPrices)
cfg.LocalApp, err = gnoland.NewApp(
nodeDir,
gnoland.GenesisAppConfig{
SkipFailingTxs: c.skipFailingGenesisTxs,
SkipSigVerification: c.skipGenesisSigVerification,
},
evsw,
logger,
minGasPrices,
)
if err != nil {
return fmt.Errorf("unable to create the Gnoland app, %w", err)
}
Expand Down Expand Up @@ -334,15 +347,15 @@ func lazyInitGenesis(
io commands.IO,
c *startCfg,
genesisPath string,
publicKey crypto.PubKey,
privateKey crypto.PrivKey,
) error {
// Check if the genesis.json is present
if osm.FileExists(genesisPath) {
return nil
}

// Generate the new genesis.json file
if err := generateGenesisFile(genesisPath, publicKey, c); err != nil {
if err := generateGenesisFile(genesisPath, privateKey, c); err != nil {
return fmt.Errorf("unable to generate genesis file, %w", err)
}

Expand All @@ -367,7 +380,21 @@ func initializeLogger(io io.WriteCloser, logLevel, logFormat string) (*zap.Logge
return log.GetZapLoggerFn(format)(io, level), nil
}

func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) error {
func generateGenesisFile(genesisFile string, privKey crypto.PrivKey, c *startCfg) error {
var (
pubKey = privKey.PubKey()
// There is an active constraint for gno.land transactions:
//
// All transaction messages' (MsgSend, MsgAddPkg...) "author" field,
// specific to the message type ("creator", "sender"...), must match
// the signature address contained in the transaction itself.
// This means that if MsgSend is originating from address A,
// the owner of the private key for address A needs to sign the transaction
// containing the message. Every message in a transaction needs to
// originate from the same account that signed the transaction
txSender = pubKey.Address()
)

gen := &bft.GenesisDoc{}
gen.GenesisTime = time.Now()
gen.ChainID = c.chainID
Expand All @@ -383,8 +410,8 @@ func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) erro

gen.Validators = []bft.GenesisValidator{
{
Address: pk.Address(),
PubKey: pk,
Address: pubKey.Address(),
PubKey: pubKey,
Power: 10,
Name: "testvalidator",
},
Expand All @@ -398,22 +425,43 @@ func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) erro

// Load examples folder
examplesDir := filepath.Join(c.gnoRootDir, "examples")
pkgsTxs, err := gnoland.LoadPackagesFromDir(examplesDir, genesisDeployAddress, genesisDeployFee)
pkgsTxs, err := gnoland.LoadPackagesFromDir(examplesDir, txSender, genesisDeployFee)
if err != nil {
return fmt.Errorf("unable to load examples folder: %w", err)
}

// Load Genesis TXs
genesisTxs, err := gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote)
if err != nil {
return fmt.Errorf("unable to load genesis txs file: %w", err)
var genesisTxs []gnoland.TxWithMetadata

if c.genesisTxsFile != "" {
genesisTxs, err = gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote)
if err != nil {
return fmt.Errorf("unable to load genesis txs file: %w", err)
}
}

genesisTxs = append(pkgsTxs, genesisTxs...)

// Sign genesis transactions, with the default key (test1)
if err = gnoland.SignGenesisTxs(genesisTxs, privKey, c.chainID); err != nil {
return fmt.Errorf("unable to sign genesis txs: %w", err)
}

// Make sure the genesis transaction author has sufficient
// balance to cover transaction deployments in genesis.
//
// During the init-chainer process, the account that authors the
// genesis transactions needs to have a sufficient balance
// to cover outstanding transaction costs.
// Since the cost can't be estimated upfront at this point, the balance
// set is an arbitrary value based on a "best guess" basis.
// There should be a larger discussion if genesis transactions should consume gas, at all
deployerBalance := int64(len(genesisTxs)) * 10_000_000 // ~10 GNOT per tx
balances.Set(txSender, std.NewCoins(std.NewCoin("ugnot", deployerBalance)))

// Construct genesis AppState.
defaultGenState := gnoland.DefaultGenState()
defaultGenState.Balances = balances
defaultGenState.Balances = balances.List()
defaultGenState.Txs = genesisTxs
gen.AppState = defaultGenState

Expand Down
22 changes: 19 additions & 3 deletions gno.land/pkg/gnoland/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,25 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {
return baseApp, nil
}

// GenesisAppConfig wraps the most important
// genesis params relating to the App
type GenesisAppConfig struct {
SkipFailingTxs bool // does not stop the chain from starting if any tx fails
SkipSigVerification bool // does not verify the transaction signatures in genesis
}

// NewTestGenesisAppConfig returns a testing genesis app config
func NewTestGenesisAppConfig() GenesisAppConfig {
return GenesisAppConfig{
SkipFailingTxs: true,
SkipSigVerification: true,
}
}

// NewApp creates the gno.land application.
func NewApp(
dataRootDir string,
skipFailingGenesisTxs bool,
genesisCfg GenesisAppConfig,
evsw events.EventSwitch,
logger *slog.Logger,
minGasPrices string,
Expand All @@ -199,9 +214,10 @@ func NewApp(
GenesisTxResultHandler: PanicOnFailingTxResultHandler,
StdlibDir: filepath.Join(gnoenv.RootDir(), "gnovm", "stdlibs"),
},
MinGasPrices: minGasPrices,
MinGasPrices: minGasPrices,
SkipGenesisVerification: genesisCfg.SkipSigVerification,
}
if skipFailingGenesisTxs {
if genesisCfg.SkipFailingTxs {
cfg.GenesisTxResultHandler = NoopGenesisTxResultHandler
}

Expand Down
2 changes: 1 addition & 1 deletion gno.land/pkg/gnoland/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func TestNewApp(t *testing.T) {
// NewApp should have good defaults and manage to run InitChain.
td := t.TempDir()

app, err := NewApp(td, true, events.NewEventSwitch(), log.NewNoopLogger(), "")
app, err := NewApp(td, NewTestGenesisAppConfig(), events.NewEventSwitch(), log.NewNoopLogger(), "")
require.NoError(t, err, "NewApp should be successful")

resp := app.InitChain(abci.RequestInitChain{
Expand Down
9 changes: 3 additions & 6 deletions gno.land/pkg/gnoland/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import (
const initGasPrice = "1ugnot/1000gas"

// LoadGenesisBalancesFile loads genesis balances from the provided file path.
func LoadGenesisBalancesFile(path string) ([]Balance, error) {
func LoadGenesisBalancesFile(path string) (Balances, error) {
// each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
content, err := osm.ReadFile(path)
if err != nil {
return nil, err
}
lines := strings.Split(string(content), "\n")

balances := make([]Balance, 0, len(lines))
balances := make(Balances, len(lines))
for _, line := range lines {
line = strings.TrimSpace(line)

Expand Down Expand Up @@ -56,10 +56,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) {
return nil, fmt.Errorf("invalid balance coins %s: %w", parts[1], err)
}

balances = append(balances, Balance{
Address: addr,
Amount: coins,
})
balances.Set(addr, coins)
}

return balances, nil
Expand Down
29 changes: 29 additions & 0 deletions gno.land/pkg/gnoland/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"

"github.com/gnolang/gno/tm2/pkg/amino"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/sdk/auth"
"github.com/gnolang/gno/tm2/pkg/std"
)
Expand Down Expand Up @@ -86,3 +87,31 @@ func ReadGenesisTxs(ctx context.Context, path string) ([]TxWithMetadata, error)

return txs, nil
}

// SignGenesisTxs will sign all txs passed as argument using the private key.
// This signature is only valid for genesis transactions as the account number and sequence are 0
func SignGenesisTxs(txs []TxWithMetadata, privKey crypto.PrivKey, chainID string) error {
for index, tx := range txs {
// Upon verifying genesis transactions, the account number and sequence are considered to be 0.
// The reason for this is that it is not possible to know the account number (or sequence!) in advance
// when generating the genesis transaction signature
bytes, err := tx.Tx.GetSignBytes(chainID, 0, 0)
if err != nil {
return fmt.Errorf("unable to get sign bytes for transaction, %w", err)
}

signature, err := privKey.Sign(bytes)
if err != nil {
return fmt.Errorf("unable to sign genesis transaction, %w", err)
}

txs[index].Tx.Signatures = []std.Signature{
{
PubKey: privKey.PubKey(),
Signature: signature,
},
}
}

return nil
}
27 changes: 27 additions & 0 deletions gno.land/pkg/gnoland/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot"
"github.com/gnolang/gno/tm2/pkg/amino"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/secp256k1"
"github.com/gnolang/gno/tm2/pkg/sdk/bank"
"github.com/gnolang/gno/tm2/pkg/std"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -129,3 +130,29 @@ func TestReadGenesisTxs(t *testing.T) {
}
})
}

func TestSignGenesisTx(t *testing.T) {
t.Parallel()

var (
txs = generateTxs(t, 100)
privKey = secp256k1.GenPrivKey()
pubKey = privKey.PubKey()
chainID = "testing"
)

// Make sure the transactions are properly signed
require.NoError(t, SignGenesisTxs(txs, privKey, chainID))

// Make sure the signatures are valid
for _, tx := range txs {
payload, err := tx.Tx.GetSignBytes(chainID, 0, 0)
require.NoError(t, err)

sigs := tx.Tx.GetSignatures()
require.Len(t, sigs, 1)

assert.True(t, pubKey.Equals(sigs[0].PubKey))
assert.True(t, pubKey.VerifyBytes(payload, sigs[0].Signature))
}
}
2 changes: 1 addition & 1 deletion gno.land/pkg/integration/node_testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balanc
genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
require.NoError(t, err)

return genesisBalances
return genesisBalances.List()
}

// LoadDefaultGenesisParamFile loads the default genesis balance file for testing.
Expand Down
3 changes: 1 addition & 2 deletions gno.land/pkg/integration/pkgloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ func (pl *PkgsLoader) LoadPackages(creatorKey crypto.PrivKey, fee std.Fee, depos
}
}

err = SignTxs(txs, creatorKey, "tendermint_test")
if err != nil {
if err = gnoland.SignGenesisTxs(txs, creatorKey, "tendermint_test"); err != nil {
return nil, fmt.Errorf("unable to sign txs: %w", err)
}

Expand Down
Loading

0 comments on commit 5a27a5e

Please sign in to comment.