Skip to content

Commit

Permalink
Make sure genesis txs have valid signatures, and creators
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Jan 9, 2025
1 parent 32ed1ab commit 50e6f91
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 43 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
50 changes: 37 additions & 13 deletions gno.land/cmd/gnoland/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,8 @@ 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
Expand Down Expand Up @@ -86,7 +83,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 @@ -105,7 +101,7 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
fs.StringVar(
&c.genesisTxsFile,
"genesis-txs-file",
defaultGenesisTxsFile,
"",
"initial txs to replay",
)

Expand Down Expand Up @@ -368,7 +364,19 @@ func initializeLogger(io io.WriteCloser, logLevel, logFormat string) (*zap.Logge
}

func generateGenesisFile(genesisFile string, privKey crypto.PrivKey, c *startCfg) error {
pubKey := privKey.PubKey()
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()
Expand Down Expand Up @@ -400,15 +408,19 @@ func generateGenesisFile(genesisFile string, privKey crypto.PrivKey, c *startCfg

// 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...)
Expand All @@ -418,9 +430,21 @@ func generateGenesisFile(genesisFile string, privKey crypto.PrivKey, c *startCfg
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
17 changes: 0 additions & 17 deletions gno.land/genesis/genesis_txs.jsonl

This file was deleted.

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
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
6 changes: 3 additions & 3 deletions tm2/pkg/sdk/auth/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func processSig(
ctx sdk.Context, acc std.Account, sig std.Signature, signBytes []byte, simulate bool, params Params,
sigGasConsumer SignatureVerificationGasConsumer,
) (updatedAcc std.Account, res sdk.Result) {
pubKey, res := ProcessPubKey(acc, sig, simulate)
pubKey, res := ProcessPubKey(acc, sig)
if !res.IsOK() {
return nil, res
}
Expand Down Expand Up @@ -243,7 +243,7 @@ func processSig(
// ProcessPubKey verifies that the given account address matches that of the
// std.Signature. In addition, it will set the public key of the account if it
// has not been set.
func ProcessPubKey(acc std.Account, sig std.Signature, simulate bool) (crypto.PubKey, sdk.Result) {
func ProcessPubKey(acc std.Account, sig std.Signature) (crypto.PubKey, sdk.Result) {
// If pubkey is not known for account, set it from the std.Signature.
pubKey := acc.GetPubKey()
if pubKey == nil {
Expand Down Expand Up @@ -271,7 +271,7 @@ func DefaultSigVerificationGasConsumer(
switch pubkey := pubkey.(type) {
case ed25519.PubKeyEd25519:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
return abciResult(std.ErrInvalidPubKey("ED25519 public keys are unsupported"))
return sdk.Result{}

case secp256k1.PubKeySecp256k1:
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
Expand Down
4 changes: 2 additions & 2 deletions tm2/pkg/sdk/auth/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ func TestProcessPubKey(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

_, err := ProcessPubKey(tt.args.acc, tt.args.sig, tt.args.simulate)
_, err := ProcessPubKey(tt.args.acc, tt.args.sig)
require.Equal(t, tt.wantErr, !err.IsOK())
})
}
Expand Down Expand Up @@ -655,7 +655,7 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
gasConsumed int64
shouldErr bool
}{
{"PubKeyEd25519", args{store.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostED25519, true},
{"PubKeyEd25519", args{store.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostED25519, false},
{"PubKeySecp256k1", args{store.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostSecp256k1, false},
{"Multisig", args{store.NewInfiniteGasMeter(), amino.MustMarshal(multisignature1), multisigKey1, params}, expectedCost1, false},
{"unknown key", args{store.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
Expand Down

0 comments on commit 50e6f91

Please sign in to comment.