Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add genesis packages with transaction signing #3280

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
aa15626
feat: add genesis packages with transaction signing
Villaquiranm Dec 5, 2024
169e2a3
fix linter
Villaquiranm Dec 5, 2024
069c01b
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 6, 2024
b46af72
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 9, 2024
4eb4f8a
fix tests
Villaquiranm Dec 9, 2024
8a72345
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 12, 2024
90e0c0c
testing fix
Villaquiranm Dec 12, 2024
af86152
sign packages by default with test1 account
Villaquiranm Dec 12, 2024
46d6129
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 12, 2024
bf39fe7
Add test
Villaquiranm Dec 12, 2024
66b1725
remove temporary fix on gnostart
Villaquiranm Dec 12, 2024
5b4aadf
change default name to dev
Villaquiranm Dec 12, 2024
98f9ae0
change back to tendermit_test
Villaquiranm Dec 12, 2024
d70fa9b
do not check verification on gnodev tests
Villaquiranm Dec 12, 2024
ed0784f
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 17, 2024
ed1c3c6
configure genesis transaction verification depending on service
Villaquiranm Dec 17, 2024
1ea0bca
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 17, 2024
8dfb9bf
Fix tests
Villaquiranm Dec 17, 2024
6c8775f
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 17, 2024
037f832
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 18, 2024
76f3fdd
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 18, 2024
c72fe3c
fix txtar tests
Villaquiranm Dec 18, 2024
d0715e9
fix TestCallSingle_Integration test
Villaquiranm Dec 18, 2024
6bc9df9
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 19, 2024
94ad25b
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 19, 2024
2bddc48
Fix tests
Villaquiranm Dec 19, 2024
8b27abe
add comment on gnoHome config
Villaquiranm Dec 19, 2024
a0d0b9c
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Dec 20, 2024
5aec227
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 20, 2024
bb2f53f
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 20, 2024
3c887a9
make tidy
Villaquiranm Dec 20, 2024
6e8c63f
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 23, 2024
9430d13
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 23, 2024
64cf627
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 25, 2024
bbc1055
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Dec 30, 2024
0394a1b
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Jan 2, 2025
7f1fbc9
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Jan 6, 2025
c967c2f
Solve comments
Villaquiranm Jan 6, 2025
14c6906
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Jan 7, 2025
09dce43
fix more comments :)
Villaquiranm Jan 7, 2025
9f59ccb
make tidy
Villaquiranm Jan 7, 2025
e33600f
sign load packages on integration tests
Villaquiranm Jan 7, 2025
2a67769
improve SignTx function
Villaquiranm Jan 8, 2025
30c5a42
Merge branch 'master' of github.com:gnolang/gno into feat/sign-transa…
Villaquiranm Jan 8, 2025
7a134ab
fix build
Villaquiranm Jan 8, 2025
cfcc35d
improve check
Villaquiranm Jan 8, 2025
6df2bc9
Merge branch 'master' into feat/sign-transactions-genesis
Villaquiranm Jan 9, 2025
e0bb164
remove creator from LoadPackages func
Villaquiranm Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions contribs/gnogenesis/internal/txs/txs_add_packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"flag"
"fmt"

"github.com/gnolang/gno/gnovm/pkg/gnoenv"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"

"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot"
Expand All @@ -16,8 +18,7 @@ import (
)

var (
errInvalidPackageDir = errors.New("invalid package directory")
errInvalidDeployerAddr = errors.New("invalid deployer address")
errInvalidPackageDir = errors.New("invalid package directory")
)

// Keep in sync with gno.land/cmd/start.go
Expand All @@ -27,16 +28,32 @@ var (
)

type addPkgCfg struct {
txsCfg *txsCfg
deployerAddress string
txsCfg *txsCfg
keyName string
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
gnoHome string
insecurePasswordStdin bool
}

func (c *addPkgCfg) RegisterFlags(fs *flag.FlagSet) {
fs.StringVar(
&c.deployerAddress,
"deployer-address",
defaultCreator.String(),
"the address that will be used to deploy the package",
&c.keyName,
"key-name",
"",
"The package deployer key name or address",
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
)

fs.StringVar(
&c.gnoHome,
"gno-home",
gnoenv.HomeDir(),
"the gno home directory",
)
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved

fs.BoolVar(
&c.insecurePasswordStdin,
"insecure-password-stdin",
false,
"the gno home directory",
)
}

Expand Down Expand Up @@ -78,14 +95,21 @@ func execTxsAddPackages(

var (
creator = defaultCreator
err error
pass string
)

// Check if the deployer address is set
if cfg.deployerAddress != defaultCreator.String() {
creator, err = crypto.AddressFromString(cfg.deployerAddress)
kb, err := keys.NewKeyBaseFromDir(cfg.gnoHome)
if err != nil {
return err
}
if cfg.keyName != "" {
info, err := kb.GetByNameOrAddress(cfg.keyName)
if err != nil {
return err
}
creator = info.GetAddress()
pass, err = io.GetPassword("Enter password.", cfg.insecurePasswordStdin)
if err != nil {
return fmt.Errorf("%w, %w", errInvalidDeployerAddr, err)
return fmt.Errorf("cannot read password: %w", err)
}
}

Expand All @@ -96,7 +120,11 @@ func execTxsAddPackages(
if err != nil {
return fmt.Errorf("unable to load txs from directory, %w", err)
}

if creator != defaultCreator {
if err := signTxs(txs, cfg.keyName, genesis.ChainID, kb, pass); err != nil {
return fmt.Errorf("unable to sign txs, %w", err)
}
}
parsedTxs = append(parsedTxs, txs...)
}

Expand All @@ -117,3 +145,24 @@ func execTxsAddPackages(

return nil
}

func signTxs(txs []gnoland.TxWithMetadata, keyName string, chainID string, kb keys.Keybase, pass string) error {
for index, tx := range txs {
signBytes, err := tx.Tx.GetSignBytes(chainID, 0, 0)
if err != nil {
return fmt.Errorf("unable to load txs from directory, %w", err)
}
signature, publicKey, err := kb.Sign(keyName, pass, signBytes)
txs[index].Tx.Signatures = []std.Signature{
{
PubKey: publicKey,
Signature: signature,
},
}
if err != nil {
return fmt.Errorf("unable sign tx %w", err)
}
}

return nil
}
176 changes: 157 additions & 19 deletions contribs/gnogenesis/internal/txs/txs_add_packages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"

"github.com/gnolang/contribs/gnogenesis/internal/common"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
"github.com/gnolang/gno/tm2/pkg/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -60,8 +63,10 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) {
assert.ErrorContains(t, cmdErr, errInvalidPackageDir.Error())
})

t.Run("invalid deployer address", func(t *testing.T) {
t.Run("nonExistentKeyName", func(t *testing.T) {
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()
keybaseDir := t.TempDir()
keyname := "beep-boop"

tempGenesis, cleanup := testutils.NewTestFile(t)
t.Cleanup(cleanup)
Expand All @@ -77,49 +82,159 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) {
"--genesis-path",
tempGenesis.Name(),
t.TempDir(), // package dir
"--deployer-address",
"beep-boop", // invalid address
"--key-name",
keyname, // non-existent key name
"--gno-home",
keybaseDir, // temporaryDir for keybase
}

// Run the command
cmdErr := cmd.ParseAndRun(context.Background(), args)
assert.ErrorIs(t, cmdErr, errInvalidDeployerAddr)
fmt.Println(cmdErr.Error())
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
assert.ErrorContains(t, cmdErr, "Key "+keyname+" not found")
})

t.Run("valid package", func(t *testing.T) {
t.Run("existentKeyBadPassword", func(t *testing.T) {
t.Parallel()

tempGenesis, cleanup := testutils.NewTestFile(t)
t.Cleanup(cleanup)

genesis := common.GetDefaultGenesis()
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))

// Prepare the package
var (
packagePath = "gno.land/p/demo/cuttlas"
dir = t.TempDir()
keybaseDir = t.TempDir()
keyname = "beep-boop"
password = "somepass"
)
createValidFile(t, dir, packagePath)
// Create key
kb, err := keys.NewKeyBaseFromDir(keybaseDir)
require.NoError(t, err)
mnemonic, err := client.GenerateMnemonic(256)
require.NoError(t, err)
_, err = kb.CreateAccount(keyname, mnemonic, "", password+"wrong", 0, 0)
require.NoError(t, err)

createFile := func(path, data string) {
file, err := os.Create(path)
require.NoError(t, err)
io := commands.NewTestIO()
io.SetIn(
strings.NewReader(
fmt.Sprintf(
"%s\n",
password,
),
),
)

_, err = file.WriteString(data)
require.NoError(t, err)
// Create the command
cmd := NewTxsCmd(io)
args := []string{
"add",
"packages",
"--genesis-path",
tempGenesis.Name(),
"--key-name",
keyname, // non-existent key name
"--gno-home",
keybaseDir, // temporaryDir for keybase
"--insecure-password-stdin",
dir,
}

// Create the gno.mod file
createFile(
filepath.Join(dir, "gno.mod"),
fmt.Sprintf("module %s\n", packagePath),
// Run the command
cmdErr := cmd.ParseAndRun(context.Background(), args)
fmt.Println(cmdErr.Error())
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
assert.ErrorContains(t, cmdErr, "unable to sign txs, unable sign tx invalid account password")
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
})

t.Run("existentKeyOKPassword", func(t *testing.T) {
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()

tempGenesis, cleanup := testutils.NewTestFile(t)
t.Cleanup(cleanup)

genesis := common.GetDefaultGenesis()
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))
// Prepare the package
var (
packagePath = "gno.land/p/demo/cuttlas"
dir = t.TempDir()
keybaseDir = t.TempDir()
keyname = "beep-boop"
password = "somepass"
)
createValidFile(t, dir, packagePath)
// Create key
kb, err := keys.NewKeyBaseFromDir(keybaseDir)
require.NoError(t, err)
mnemonic, err := client.GenerateMnemonic(256)
require.NoError(t, err)
_, err = kb.CreateAccount(keyname, mnemonic, "", password, 0, 0)
require.NoError(t, err)

io := commands.NewTestIO()
io.SetIn(
strings.NewReader(
fmt.Sprintf(
"%s\n",
password,
),
),
)

// Create a simple main.gno
createFile(
filepath.Join(dir, "main.gno"),
"package cuttlas\n\nfunc Example() string {\nreturn \"Manos arriba!\"\n}",
// Create the command
cmd := NewTxsCmd(io)
args := []string{
"add",
"packages",
"--genesis-path",
tempGenesis.Name(),
"--key-name",
keyname, // non-existent key name
"--gno-home",
keybaseDir, // temporaryDir for keybase
"--insecure-password-stdin",
dir,
}

// Run the command
cmdErr := cmd.ParseAndRun(context.Background(), args)
require.NoError(t, cmdErr)

// Validate the transactions were written down
updatedGenesis, err := types.GenesisDocFromFile(tempGenesis.Name())
require.NoError(t, err)
require.NotNil(t, updatedGenesis.AppState)

// Fetch the state
state := updatedGenesis.AppState.(gnoland.GnoGenesisState)

require.Equal(t, 1, len(state.Txs))
require.Equal(t, 1, len(state.Txs[0].Tx.Msgs))

msgAddPkg, ok := state.Txs[0].Tx.Msgs[0].(vmm.MsgAddPackage)
require.True(t, ok)

assert.Equal(t, packagePath, msgAddPkg.Package.Path)
})

t.Run("valid package", func(t *testing.T) {
t.Parallel()

tempGenesis, cleanup := testutils.NewTestFile(t)
t.Cleanup(cleanup)

genesis := common.GetDefaultGenesis()
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))
// Prepare the package
var (
packagePath = "gno.land/p/demo/cuttlas"
dir = t.TempDir()
)
createValidFile(t, dir, packagePath)

// Create the command
cmd := NewTxsCmd(commands.NewTestIO())
Expand Down Expand Up @@ -152,3 +267,26 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) {
assert.Equal(t, packagePath, msgAddPkg.Package.Path)
})
}

func createValidFile(t *testing.T, dir string, packagePath string) {
t.Helper()
createFile := func(path, data string) {
file, err := os.Create(path)
require.NoError(t, err)

_, err = file.WriteString(data)
require.NoError(t, err)
}

// Create the gno.mod file
createFile(
filepath.Join(dir, "gno.mod"),
fmt.Sprintf("module %s\n", packagePath),
)

// Create a simple main.gno
createFile(
filepath.Join(dir, "main.gno"),
"package cuttlas\n\nfunc Example() string {\nreturn \"Manos arriba!\"\n}",
)
}
2 changes: 1 addition & 1 deletion gno.land/pkg/gnoland/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {

// Set AnteHandler
authOptions := auth.AnteOptions{
VerifyGenesisSignatures: false, // for development
VerifyGenesisSignatures: true,
}
authAnteHandler := auth.NewAnteHandler(
acctKpr, bankKpr, auth.DefaultSigVerificationGasConsumer, authOptions)
Expand Down
4 changes: 3 additions & 1 deletion tm2/pkg/sdk/auth/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,15 +394,17 @@ func SetGasMeter(simulate bool, ctx sdk.Context, gasLimit int64) sdk.Context {
// and an account.
func GetSignBytes(chainID string, tx std.Tx, acc std.Account, genesis bool) ([]byte, error) {
var accNum uint64
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
var accSequence uint64
if !genesis {
accNum = acc.GetAccountNumber()
accSequence = acc.GetSequence()
}

return std.GetSignaturePayload(
std.SignDoc{
ChainID: chainID,
AccountNumber: accNum,
Sequence: acc.GetSequence(),
Sequence: accSequence,
Fee: tx.Fee,
Msgs: tx.Msgs,
Memo: tx.Memo,
Expand Down
Loading
Loading