Skip to content

Commit

Permalink
Add support for signing lazily loaded transactions in genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Jan 9, 2025
1 parent 41f8763 commit 32ed1ab
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 41 deletions.
19 changes: 13 additions & 6 deletions gno.land/cmd/gnoland/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,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 Down Expand Up @@ -334,15 +334,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 +367,9 @@ 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 {
pubKey := privKey.PubKey()

gen := &bft.GenesisDoc{}
gen.GenesisTime = time.Now()
gen.ChainID = c.chainID
Expand All @@ -383,8 +385,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 @@ -411,6 +413,11 @@ func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) erro

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)
}

// Construct genesis AppState.
defaultGenState := gnoland.DefaultGenState()
defaultGenState.Balances = balances
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))
}
}
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
33 changes: 0 additions & 33 deletions gno.land/pkg/integration/signer.go

This file was deleted.

0 comments on commit 32ed1ab

Please sign in to comment.