Skip to content

Commit 7523824

Browse files
committed
chore: Merge remote-tracking branch 'origin/master' into gno-resolver
2 parents 740e3e3 + 1b89166 commit 7523824

File tree

18 files changed

+210
-115
lines changed

18 files changed

+210
-115
lines changed

contribs/gnogenesis/internal/txs/txs_add_packages.go

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818

1919
const (
2020
defaultAccount_Name = "test1"
21-
defaultAccount_Address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
2221
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"
2322
defaultAccount_publicKey = "gpub1pgfj7ard9eg82cjtv4u4xetrwqer2dntxyfzxz3pq0skzdkmzu0r9h6gny6eg8c9dc303xrrudee6z4he4y7cs5rnjwmyf40yaj"
2423
)

gno.land/cmd/gnoland/start.go

+76-28
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,20 @@ var startGraphic = strings.ReplaceAll(`
4646
/___/
4747
`, "'", "`")
4848

49-
var (
50-
// Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go
51-
genesisDeployAddress = crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // test1
52-
genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000)))
53-
)
49+
// Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go
50+
var genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000)))
5451

5552
type startCfg struct {
56-
gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
57-
skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
58-
genesisBalancesFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
59-
genesisTxsFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
60-
genesisRemote string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
61-
genesisFile string
62-
chainID string
63-
dataDir string
64-
lazyInit bool
53+
gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
54+
skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
55+
skipGenesisSigVerification bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
56+
genesisBalancesFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
57+
genesisTxsFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
58+
genesisRemote string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952
59+
genesisFile string
60+
chainID string
61+
dataDir string
62+
lazyInit bool
6563

6664
logLevel string
6765
logFormat string
@@ -87,7 +85,6 @@ func newStartCmd(io commands.IO) *commands.Command {
8785
func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
8886
gnoroot := gnoenv.RootDir()
8987
defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
90-
defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.jsonl")
9188

9289
fs.BoolVar(
9390
&c.skipFailingGenesisTxs,
@@ -96,6 +93,13 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
9693
"don't panic when replaying invalid genesis txs",
9794
)
9895

96+
fs.BoolVar(
97+
&c.skipGenesisSigVerification,
98+
"skip-genesis-sig-verification",
99+
false,
100+
"don't panic when replaying invalidly signed genesis txs",
101+
)
102+
99103
fs.StringVar(
100104
&c.genesisBalancesFile,
101105
"genesis-balances-file",
@@ -106,7 +110,7 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
106110
fs.StringVar(
107111
&c.genesisTxsFile,
108112
"genesis-txs-file",
109-
defaultGenesisTxsFile,
113+
"",
110114
"initial txs to replay",
111115
)
112116

@@ -219,7 +223,7 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error {
219223
)
220224

221225
// Init a new genesis.json
222-
if err := lazyInitGenesis(io, c, genesisPath, privateKey.GetPubKey()); err != nil {
226+
if err := lazyInitGenesis(io, c, genesisPath, privateKey.Key.PrivKey); err != nil {
223227
return fmt.Errorf("unable to initialize genesis.json, %w", err)
224228
}
225229
}
@@ -239,7 +243,16 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error {
239243
minGasPrices := cfg.Application.MinGasPrices
240244

241245
// Create application and node
242-
cfg.LocalApp, err = gnoland.NewApp(nodeDir, c.skipFailingGenesisTxs, evsw, logger, minGasPrices)
246+
cfg.LocalApp, err = gnoland.NewApp(
247+
nodeDir,
248+
gnoland.GenesisAppConfig{
249+
SkipFailingTxs: c.skipFailingGenesisTxs,
250+
SkipSigVerification: c.skipGenesisSigVerification,
251+
},
252+
evsw,
253+
logger,
254+
minGasPrices,
255+
)
243256
if err != nil {
244257
return fmt.Errorf("unable to create the Gnoland app, %w", err)
245258
}
@@ -335,15 +348,15 @@ func lazyInitGenesis(
335348
io commands.IO,
336349
c *startCfg,
337350
genesisPath string,
338-
publicKey crypto.PubKey,
351+
privateKey crypto.PrivKey,
339352
) error {
340353
// Check if the genesis.json is present
341354
if osm.FileExists(genesisPath) {
342355
return nil
343356
}
344357

345358
// Generate the new genesis.json file
346-
if err := generateGenesisFile(io, genesisPath, publicKey, c); err != nil {
359+
if err := generateGenesisFile(io, genesisPath, privateKey, c); err != nil {
347360
return fmt.Errorf("unable to generate genesis file, %w", err)
348361
}
349362

@@ -368,7 +381,21 @@ func initializeLogger(io io.WriteCloser, logLevel, logFormat string) (*zap.Logge
368381
return log.GetZapLoggerFn(format)(io, level), nil
369382
}
370383

371-
func generateGenesisFile(io commands.IO, genesisFile string, pk crypto.PubKey, c *startCfg) error {
384+
func generateGenesisFile(io commands.IO, genesisFile string, privKey crypto.PrivKey, c *startCfg) error {
385+
var (
386+
pubKey = privKey.PubKey()
387+
// There is an active constraint for gno.land transactions:
388+
//
389+
// All transaction messages' (MsgSend, MsgAddPkg...) "author" field,
390+
// specific to the message type ("creator", "sender"...), must match
391+
// the signature address contained in the transaction itself.
392+
// This means that if MsgSend is originating from address A,
393+
// the owner of the private key for address A needs to sign the transaction
394+
// containing the message. Every message in a transaction needs to
395+
// originate from the same account that signed the transaction
396+
txSender = pubKey.Address()
397+
)
398+
372399
gen := &bft.GenesisDoc{}
373400
gen.GenesisTime = time.Now()
374401
gen.ChainID = c.chainID
@@ -384,8 +411,8 @@ func generateGenesisFile(io commands.IO, genesisFile string, pk crypto.PubKey, c
384411

385412
gen.Validators = []bft.GenesisValidator{
386413
{
387-
Address: pk.Address(),
388-
PubKey: pk,
414+
Address: pubKey.Address(),
415+
PubKey: pubKey,
389416
Power: 10,
390417
Name: "testvalidator",
391418
},
@@ -400,22 +427,43 @@ func generateGenesisFile(io commands.IO, genesisFile string, pk crypto.PubKey, c
400427
// Load examples folder
401428
examplesDir := filepath.Join(c.gnoRootDir, "examples")
402429
loadCfg := &packages.LoadConfig{IO: io, SelfContained: true}
403-
pkgsTxs, err := gnoland.LoadPackagesFromDir(loadCfg, examplesDir, genesisDeployAddress, genesisDeployFee)
430+
pkgsTxs, err := gnoland.LoadPackagesFromDir(loadCfg, examplesDir, txSender, genesisDeployFee)
404431
if err != nil {
405432
return fmt.Errorf("unable to load examples folder: %w", err)
406433
}
407434

408435
// Load Genesis TXs
409-
genesisTxs, err := gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote)
410-
if err != nil {
411-
return fmt.Errorf("unable to load genesis txs file: %w", err)
436+
var genesisTxs []gnoland.TxWithMetadata
437+
438+
if c.genesisTxsFile != "" {
439+
genesisTxs, err = gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote)
440+
if err != nil {
441+
return fmt.Errorf("unable to load genesis txs file: %w", err)
442+
}
412443
}
413444

414445
genesisTxs = append(pkgsTxs, genesisTxs...)
415446

447+
// Sign genesis transactions, with the default key (test1)
448+
if err = gnoland.SignGenesisTxs(genesisTxs, privKey, c.chainID); err != nil {
449+
return fmt.Errorf("unable to sign genesis txs: %w", err)
450+
}
451+
452+
// Make sure the genesis transaction author has sufficient
453+
// balance to cover transaction deployments in genesis.
454+
//
455+
// During the init-chainer process, the account that authors the
456+
// genesis transactions needs to have a sufficient balance
457+
// to cover outstanding transaction costs.
458+
// Since the cost can't be estimated upfront at this point, the balance
459+
// set is an arbitrary value based on a "best guess" basis.
460+
// There should be a larger discussion if genesis transactions should consume gas, at all
461+
deployerBalance := int64(len(genesisTxs)) * 10_000_000 // ~10 GNOT per tx
462+
balances.Set(txSender, std.NewCoins(std.NewCoin("ugnot", deployerBalance)))
463+
416464
// Construct genesis AppState.
417465
defaultGenState := gnoland.DefaultGenState()
418-
defaultGenState.Balances = balances
466+
defaultGenState.Balances = balances.List()
419467
defaultGenState.Txs = genesisTxs
420468
gen.AppState = defaultGenState
421469

gno.land/pkg/gnoland/app.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,25 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {
182182
return baseApp, nil
183183
}
184184

185+
// GenesisAppConfig wraps the most important
186+
// genesis params relating to the App
187+
type GenesisAppConfig struct {
188+
SkipFailingTxs bool // does not stop the chain from starting if any tx fails
189+
SkipSigVerification bool // does not verify the transaction signatures in genesis
190+
}
191+
192+
// NewTestGenesisAppConfig returns a testing genesis app config
193+
func NewTestGenesisAppConfig() GenesisAppConfig {
194+
return GenesisAppConfig{
195+
SkipFailingTxs: true,
196+
SkipSigVerification: true,
197+
}
198+
}
199+
185200
// NewApp creates the gno.land application.
186201
func NewApp(
187202
dataRootDir string,
188-
skipFailingGenesisTxs bool,
203+
genesisCfg GenesisAppConfig,
189204
evsw events.EventSwitch,
190205
logger *slog.Logger,
191206
minGasPrices string,
@@ -199,9 +214,10 @@ func NewApp(
199214
GenesisTxResultHandler: PanicOnFailingTxResultHandler,
200215
StdlibDir: filepath.Join(gnoenv.RootDir(), "gnovm", "stdlibs"),
201216
},
202-
MinGasPrices: minGasPrices,
217+
MinGasPrices: minGasPrices,
218+
SkipGenesisVerification: genesisCfg.SkipSigVerification,
203219
}
204-
if skipFailingGenesisTxs {
220+
if genesisCfg.SkipFailingTxs {
205221
cfg.GenesisTxResultHandler = NoopGenesisTxResultHandler
206222
}
207223

gno.land/pkg/gnoland/app_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func TestNewApp(t *testing.T) {
134134
// NewApp should have good defaults and manage to run InitChain.
135135
td := t.TempDir()
136136

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

140140
resp := app.InitChain(abci.RequestInitChain{

gno.land/pkg/gnoland/genesis.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ import (
2121
const initGasPrice = "1ugnot/1000gas"
2222

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

32-
balances := make([]Balance, 0, len(lines))
32+
balances := make(Balances, len(lines))
3333
for _, line := range lines {
3434
line = strings.TrimSpace(line)
3535

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

60-
balances = append(balances, Balance{
61-
Address: addr,
62-
Amount: coins,
63-
})
60+
balances.Set(addr, coins)
6461
}
6562

6663
return balances, nil

gno.land/pkg/gnoland/types.go

+29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99

1010
"github.com/gnolang/gno/tm2/pkg/amino"
11+
"github.com/gnolang/gno/tm2/pkg/crypto"
1112
"github.com/gnolang/gno/tm2/pkg/sdk/auth"
1213
"github.com/gnolang/gno/tm2/pkg/std"
1314
)
@@ -86,3 +87,31 @@ func ReadGenesisTxs(ctx context.Context, path string) ([]TxWithMetadata, error)
8687

8788
return txs, nil
8889
}
90+
91+
// SignGenesisTxs will sign all txs passed as argument using the private key.
92+
// This signature is only valid for genesis transactions as the account number and sequence are 0
93+
func SignGenesisTxs(txs []TxWithMetadata, privKey crypto.PrivKey, chainID string) error {
94+
for index, tx := range txs {
95+
// Upon verifying genesis transactions, the account number and sequence are considered to be 0.
96+
// The reason for this is that it is not possible to know the account number (or sequence!) in advance
97+
// when generating the genesis transaction signature
98+
bytes, err := tx.Tx.GetSignBytes(chainID, 0, 0)
99+
if err != nil {
100+
return fmt.Errorf("unable to get sign bytes for transaction, %w", err)
101+
}
102+
103+
signature, err := privKey.Sign(bytes)
104+
if err != nil {
105+
return fmt.Errorf("unable to sign genesis transaction, %w", err)
106+
}
107+
108+
txs[index].Tx.Signatures = []std.Signature{
109+
{
110+
PubKey: privKey.PubKey(),
111+
Signature: signature,
112+
},
113+
}
114+
}
115+
116+
return nil
117+
}

gno.land/pkg/gnoland/types_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot"
1212
"github.com/gnolang/gno/tm2/pkg/amino"
1313
"github.com/gnolang/gno/tm2/pkg/crypto"
14+
"github.com/gnolang/gno/tm2/pkg/crypto/secp256k1"
1415
"github.com/gnolang/gno/tm2/pkg/sdk/bank"
1516
"github.com/gnolang/gno/tm2/pkg/std"
1617
"github.com/stretchr/testify/assert"
@@ -129,3 +130,29 @@ func TestReadGenesisTxs(t *testing.T) {
129130
}
130131
})
131132
}
133+
134+
func TestSignGenesisTx(t *testing.T) {
135+
t.Parallel()
136+
137+
var (
138+
txs = generateTxs(t, 100)
139+
privKey = secp256k1.GenPrivKey()
140+
pubKey = privKey.PubKey()
141+
chainID = "testing"
142+
)
143+
144+
// Make sure the transactions are properly signed
145+
require.NoError(t, SignGenesisTxs(txs, privKey, chainID))
146+
147+
// Make sure the signatures are valid
148+
for _, tx := range txs {
149+
payload, err := tx.Tx.GetSignBytes(chainID, 0, 0)
150+
require.NoError(t, err)
151+
152+
sigs := tx.Tx.GetSignatures()
153+
require.Len(t, sigs, 1)
154+
155+
assert.True(t, pubKey.Equals(sigs[0].PubKey))
156+
assert.True(t, pubKey.VerifyBytes(payload, sigs[0].Signature))
157+
}
158+
}

gno.land/pkg/integration/node_testing.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balanc
150150
genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
151151
require.NoError(t, err)
152152

153-
return genesisBalances
153+
return genesisBalances.List()
154154
}
155155

156156
// LoadDefaultGenesisParamFile loads the default genesis balance file for testing.

gno.land/pkg/integration/pkgloader.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ func (pl *PkgsLoader) LoadPackages(creatorKey crypto.PrivKey, fee std.Fee, depos
7777
}
7878
}
7979

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

0 commit comments

Comments
 (0)