From 22a62ae82f6861df39b83caedf79e6897e0b85a2 Mon Sep 17 00:00:00 2001 From: Mantre Date: Sun, 4 Aug 2024 01:50:23 +0800 Subject: [PATCH 01/25] fix(util): remove util.Now helper function (#1442) --- consensus/consensus.go | 2 +- consensus/height.go | 5 +++-- execution/executor/bond_test.go | 2 +- genesis/genesis_test.go | 2 +- node/node.go | 11 +++++------ node/node_test.go | 28 +++++++++++++++++++++++++--- state/execution_test.go | 17 ++++++++--------- state/lastinfo/last_info_test.go | 4 ++-- state/state.go | 2 +- tests/main_test.go | 2 +- util/testsuite/testsuite.go | 2 +- util/time.go | 6 ------ util/time_test.go | 4 ++-- 13 files changed, 51 insertions(+), 36 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index b68253c7c..0f9d4bd43 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -376,7 +376,7 @@ func (cs *consensus) signAddVote(v *vote.Vote) { _, err := cs.log.AddVote(v) if err != nil { - cs.logger.Error("error on adding our vote", "error", err, "vote", v) + cs.logger.Warn("error on adding our vote", "error", err, "vote", v) } cs.broadcastVote(v) } diff --git a/consensus/height.go b/consensus/height.go index 3d92c52d6..9587d57f5 100644 --- a/consensus/height.go +++ b/consensus/height.go @@ -1,9 +1,10 @@ package consensus import ( + "time" + "github.com/pactus-project/pactus/types/proposal" "github.com/pactus-project/pactus/types/vote" - "github.com/pactus-project/pactus/util" ) type newHeightState struct { @@ -25,7 +26,7 @@ func (s *newHeightState) decide() { s.active = s.bcState.IsInCommittee(s.valKey.Address()) s.logger.Info("entering new height", "height", s.height, "active", s.active) - sleep := s.bcState.LastBlockTime().Add(s.bcState.Params().BlockInterval()).Sub(util.Now()) + sleep := time.Until(s.bcState.LastBlockTime().Add(s.bcState.Params().BlockInterval())) s.scheduleTimeout(sleep, s.height, s.round, tickerTargetNewHeight) } diff --git a/execution/executor/bond_test.go b/execution/executor/bond_test.go index f36bb6f6f..6ae24e6b9 100644 --- a/execution/executor/bond_test.go +++ b/execution/executor/bond_test.go @@ -81,7 +81,7 @@ func TestExecuteBondTx(t *testing.T) { t.Run("Should fail, inside committee", func(t *testing.T) { pub0 := td.sandbox.Committee().Proposer(0).PublicKey() - trx := tx.NewBondTx(lockTime, senderAddr, pub0.ValidatorAddress(), nil, amt, fee) + trx := tx.NewBondTx(lockTime, senderAddr, pub0.ValidatorAddress(), nil, 1e9, fee) td.check(t, trx, true, ErrValidatorInCommittee) td.check(t, trx, false, nil) diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go index ebdefd9eb..56e3284fc 100644 --- a/genesis/genesis_test.go +++ b/genesis/genesis_test.go @@ -95,7 +95,7 @@ func TestCheckGenesisAccountAndValidator(t *testing.T) { accs[pub.AccountAddress()] = acc vals = append(vals, val) } - gen := genesis.MakeGenesis(util.Now(), accs, vals, param.DefaultParams()) + gen := genesis.MakeGenesis(time.Now(), accs, vals, param.DefaultParams()) for addr, acc := range gen.Accounts() { assert.Equal(t, accs[addr], acc) diff --git a/node/node.go b/node/node.go index b4858d1d3..6d88ae884 100644 --- a/node/node.go +++ b/node/node.go @@ -15,7 +15,6 @@ import ( "github.com/pactus-project/pactus/sync/bundle/message" "github.com/pactus-project/pactus/sync/peerset/peer/service" "github.com/pactus-project/pactus/txpool" - "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/logger" "github.com/pactus-project/pactus/version" "github.com/pactus-project/pactus/wallet" @@ -116,7 +115,7 @@ func NewNode(genDoc *genesis.Genesis, conf *config.Config, } func (n *Node) Start() error { - now := util.Now() + now := time.Now() genTime := n.genesisDoc.GenesisTime() if genTime.After(now) { logger.Info("💤 Genesis time is in the future. Sleeping until then...", @@ -125,17 +124,17 @@ func (n *Node) Start() error { } if err := n.network.Start(); err != nil { - return err + return errors.Wrap(err, "could not start Network") } // Wait for network to start time.Sleep(1 * time.Second) if err := n.sync.Start(); err != nil { - return err + return errors.Wrap(err, "could not start Sync") } if err := n.consMgr.Start(); err != nil { - return err + return errors.Wrap(err, "could not start Consensus manager") } err := n.grpc.StartServer() @@ -155,7 +154,7 @@ func (n *Node) Start() error { err = n.nanomsg.StartServer() if err != nil { - return errors.Wrap(err, "could not start nanomsg server") + return errors.Wrap(err, "could not start Nanomsg server") } return nil diff --git a/node/node_test.go b/node/node_test.go index ddfe57014..2cfc4f107 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -2,6 +2,7 @@ package node import ( "testing" + "time" "github.com/pactus-project/pactus/config" "github.com/pactus-project/pactus/crypto" @@ -27,12 +28,20 @@ func TestRunningNode(t *testing.T) { acc := account.NewAccount(0) acc.AddToBalance(21 * 1e14) val := validator.NewValidator(pub, 0) - gen := genesis.MakeGenesis(util.Now(), + gen := genesis.MakeGenesis(time.Now(), map[crypto.Address]*account.Account{crypto.TreasuryAddress: acc}, []*validator.Validator{val}, param.DefaultParams()) conf := config.DefaultConfigMainnet() - conf.GRPC.Enable = false - conf.HTTP.Enable = false + conf.GRPC.Enable = true + conf.GRPC.Listen = "0.0.0.0:0" + conf.GRPC.Gateway.Enable = true + conf.GRPC.Gateway.Listen = "0.0.0.0:0" + conf.HTTP.Enable = true + conf.HTTP.Listen = "0.0.0.0:0" + conf.JSONRPC.Enable = true + conf.JSONRPC.Listen = "0.0.0.0:0" + conf.Nanomsg.Enable = true + conf.Nanomsg.Listen = "tcp://0.0.0.0:0" conf.Store.Path = util.TempDirPath() conf.Network.EnableRelay = false conf.Network.NetworkKey = util.TempFilePath() @@ -49,5 +58,18 @@ func TestRunningNode(t *testing.T) { err = nd.Start() require.NoError(t, err) + + consHeight, _ := nd.ConsManager().HeightRound() + assert.Equal(t, uint32(1), consHeight) + + lastBlockTime := nd.State().LastBlockTime() + assert.Equal(t, gen.GenesisTime(), lastBlockTime) + + syncSelfID := nd.Sync().SelfID() + netSelfID := nd.Network().SelfID() + assert.Equal(t, syncSelfID, netSelfID) + + assert.NotEmpty(t, nd.GRPC().Address()) + nd.Stop() } diff --git a/state/execution_test.go b/state/execution_test.go index 7b6554e21..8e865b496 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -2,11 +2,11 @@ package state import ( "testing" + "time" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/tx" - "github.com/pactus-project/pactus/util" "github.com/stretchr/testify/assert" ) @@ -15,8 +15,7 @@ func TestProposeBlock(t *testing.T) { proposer := td.state.Proposer(0) lockTime := td.state.LastBlockHeight() - dupSubsidyTx := tx.NewSubsidyTx(lockTime, proposer.Address(), - td.state.params.BlockReward, tx.WithMemo("duplicated subsidy transaction")) + dupSubsidyTx := tx.NewSubsidyTx(lockTime, proposer.Address(), td.state.params.BlockReward) invTransferTx := td.GenerateTestTransferTx() invBondTx := td.GenerateTestBondTx() invSortitionTx := td.GenerateTestSortitionTx() @@ -71,7 +70,7 @@ func TestExecuteBlock(t *testing.T) { t.Run("Subsidy tx is invalid", func(t *testing.T) { txs := block.NewTxs() txs.Append(invSubsidyTx) - invBlock := block.MakeBlock(1, util.Now(), txs, td.state.lastInfo.BlockHash(), + invBlock := block.MakeBlock(1, time.Now(), txs, td.state.lastInfo.BlockHash(), td.state.stateRoot(), td.state.lastInfo.Certificate(), td.state.lastInfo.SortitionSeed(), proposerAddr) sb := td.state.concreteSandbox() @@ -83,7 +82,7 @@ func TestExecuteBlock(t *testing.T) { txs := block.NewTxs() txs.Append(validSubsidyTx) txs.Append(invTransferTx) - invBlock := block.MakeBlock(1, util.Now(), txs, td.state.lastInfo.BlockHash(), + invBlock := block.MakeBlock(1, time.Now(), txs, td.state.lastInfo.BlockHash(), td.state.stateRoot(), td.state.lastInfo.Certificate(), td.state.lastInfo.SortitionSeed(), proposerAddr) sb := td.state.concreteSandbox() @@ -95,7 +94,7 @@ func TestExecuteBlock(t *testing.T) { txs := block.NewTxs() txs.Append(validTx1) txs.Append(validSubsidyTx) - invBlock := block.MakeBlock(1, util.Now(), txs, td.state.lastInfo.BlockHash(), + invBlock := block.MakeBlock(1, time.Now(), txs, td.state.lastInfo.BlockHash(), td.state.stateRoot(), td.state.lastInfo.Certificate(), td.state.lastInfo.SortitionSeed(), proposerAddr) sb := td.state.concreteSandbox() @@ -106,7 +105,7 @@ func TestExecuteBlock(t *testing.T) { t.Run("Has no subsidy", func(t *testing.T) { txs := block.NewTxs() txs.Append(validTx1) - invBlock := block.MakeBlock(1, util.Now(), txs, td.state.lastInfo.BlockHash(), + invBlock := block.MakeBlock(1, time.Now(), txs, td.state.lastInfo.BlockHash(), td.state.stateRoot(), td.state.lastInfo.Certificate(), td.state.lastInfo.SortitionSeed(), proposerAddr) sb := td.state.concreteSandbox() @@ -118,7 +117,7 @@ func TestExecuteBlock(t *testing.T) { txs := block.NewTxs() txs.Append(validSubsidyTx) txs.Append(validSubsidyTx) - invBlock := block.MakeBlock(1, util.Now(), txs, td.state.lastInfo.BlockHash(), + invBlock := block.MakeBlock(1, time.Now(), txs, td.state.lastInfo.BlockHash(), td.state.stateRoot(), td.state.lastInfo.Certificate(), td.state.lastInfo.SortitionSeed(), proposerAddr) sb := td.state.concreteSandbox() @@ -130,7 +129,7 @@ func TestExecuteBlock(t *testing.T) { txs := block.NewTxs() txs.Append(validSubsidyTx) txs.Append(validTx1) - invBlock := block.MakeBlock(1, util.Now(), txs, td.state.lastInfo.BlockHash(), + invBlock := block.MakeBlock(1, time.Now(), txs, td.state.lastInfo.BlockHash(), td.state.stateRoot(), td.state.lastInfo.Certificate(), td.state.lastInfo.SortitionSeed(), proposerAddr) sb := td.state.concreteSandbox() diff --git a/state/lastinfo/last_info_test.go b/state/lastinfo/last_info_test.go index d64697232..3a901f52e 100644 --- a/state/lastinfo/last_info_test.go +++ b/state/lastinfo/last_info_test.go @@ -2,6 +2,7 @@ package lastinfo import ( "testing" + "time" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" @@ -11,7 +12,6 @@ import ( "github.com/pactus-project/pactus/types/certificate" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/validator" - "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/testsuite" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -75,7 +75,7 @@ func setup(t *testing.T) *testData { lastHeight := ts.RandHeight() prevCert := ts.GenerateTestBlockCertificate(lastHeight - 1) lastSeed := ts.RandSeed() - lastBlock := block.MakeBlock(1, util.Now(), block.Txs{trx}, + lastBlock := block.MakeBlock(1, time.Now(), block.Txs{trx}, prevHash, ts.RandHash(), prevCert, lastSeed, val2.Address()) diff --git a/state/state.go b/state/state.go index c0d437f5c..e9ab9ad46 100644 --- a/state/state.go +++ b/state/state.go @@ -588,7 +588,7 @@ func (st *state) CommitteePower() int64 { func (st *state) proposeNextBlockTime() time.Time { timestamp := st.lastInfo.BlockTime().Add(st.params.BlockInterval()) - now := util.Now() + now := time.Now() if now.After(timestamp.Add(10 * time.Second)) { st.logger.Debug("it looks the last block had delay", "delay", now.Sub(timestamp)) timestamp = util.RoundNow(st.params.BlockIntervalInSecond) diff --git a/tests/main_test.go b/tests/main_test.go index 45730a85f..5578a48d6 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -125,7 +125,7 @@ func TestMain(m *testing.M) { params.BondInterval = 8 params.CommitteeSize = tCommitteeSize params.TransactionToLiveInterval = 8 - tGenDoc = genesis.MakeGenesis(util.Now(), accs, vals, params) + tGenDoc = genesis.MakeGenesis(time.Now(), accs, vals, params) for i := 0; i < tTotalNodes; i++ { tNodes[i], _ = node.NewNode( diff --git a/util/testsuite/testsuite.go b/util/testsuite/testsuite.go index cfbbadc5b..b717d9467 100644 --- a/util/testsuite/testsuite.go +++ b/util/testsuite/testsuite.go @@ -344,7 +344,7 @@ func (ts *TestSuite) NewBlockMaker() *BlockMaker { Version: 1, Txs: txs, Proposer: ts.RandValAddress(), - Time: util.Now(), + Time: time.Now(), PrevHash: ts.RandHash(), Seed: ts.RandSeed(), PrevCert: nil, diff --git a/util/time.go b/util/time.go index f88b6676e..d10d77eda 100644 --- a/util/time.go +++ b/util/time.go @@ -4,12 +4,6 @@ import ( "time" ) -// Now returns the rounded current time in UTC. -// The rounding behavior is rounding down. -func Now() time.Time { - return RoundNow(1) -} - // RoundNow returns the result of rounding sec to the current time in UTC. // The rounding behavior is rounding down. func RoundNow(sec int) time.Time { diff --git a/util/time_test.go b/util/time_test.go index b9769073b..13cea5418 100644 --- a/util/time_test.go +++ b/util/time_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" ) -func TestNow(t *testing.T) { +func TestRoundNow(t *testing.T) { c1 := time.Now() - c2 := Now() + c2 := RoundNow(1) c3 := RoundNow(5) assert.NotEqual(t, c1, c2) From 36bfcceb1a3517a392f1cfce93b9b3ee2f1e481e Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Sun, 4 Aug 2024 17:08:10 +0330 Subject: [PATCH 02/25] fix(grpc): add basic check for grpc configuration to check basic auth (#1455) --- config/config.go | 3 +++ www/grpc/config.go | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/config/config.go b/config/config.go index 4d77a9f50..e7f8b8259 100644 --- a/config/config.go +++ b/config/config.go @@ -288,6 +288,9 @@ func (conf *Config) BasicCheck() error { if err := conf.JSONRPC.BasicCheck(); err != nil { return err } + if err := conf.GRPC.BasicCheck(); err != nil { + return err + } return conf.HTTP.BasicCheck() } diff --git a/www/grpc/config.go b/www/grpc/config.go index a8b09e582..a413833c2 100644 --- a/www/grpc/config.go +++ b/www/grpc/config.go @@ -1,5 +1,7 @@ package grpc +import "github.com/pactus-project/pactus/util/htpasswd" + type Config struct { Enable bool `toml:"enable"` EnableWallet bool `toml:"enable_wallet"` @@ -23,3 +25,13 @@ func DefaultConfig() *Config { }, } } + +func (c *Config) BasicCheck() error { + if c.BasicAuth != "" { + if _, _, err := htpasswd.ExtractBasicAuth(c.BasicAuth); err != nil { + return err + } + } + + return nil +} From e0fb8323ca0a1223faf1b3b0d8a62de8a0112ad1 Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Wed, 7 Aug 2024 16:09:37 +0330 Subject: [PATCH 03/25] feat(cmd): pactus-shell support interactive shell (#1460) --- cmd/shell/main.go | 82 +++++++++++-- go.mod | 12 +- go.sum | 28 ++++- util/shell/shell.go | 250 +++++++++++++++++++++++++++++++++++++++ util/shell/shell_test.go | 150 +++++++++++++++++++++++ 5 files changed, 502 insertions(+), 20 deletions(-) create mode 100644 util/shell/shell.go create mode 100644 util/shell/shell_test.go diff --git a/cmd/shell/main.go b/cmd/shell/main.go index 7bf5352ff..a3a46a896 100644 --- a/cmd/shell/main.go +++ b/cmd/shell/main.go @@ -6,7 +6,10 @@ import ( "github.com/NathanBaulch/protoc-gen-cobra/client" "github.com/NathanBaulch/protoc-gen-cobra/naming" + "github.com/c-bata/go-prompt" + "github.com/inancgumus/screen" "github.com/pactus-project/pactus/cmd" + "github.com/pactus-project/pactus/util/shell" pb "github.com/pactus-project/pactus/www/grpc/gen/go" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -18,10 +21,13 @@ const ( defaultResponseFormat = "prettyjson" ) +var _prefix string + func main() { var ( - username string - password string + serverAddr string + username string + password string ) rootCmd := &cobra.Command{ @@ -30,11 +36,42 @@ func main() { Long: `pactus-shell is a command line tool for interacting with the Pactus blockchain using gRPC`, } + sh := shell.New(rootCmd, nil, + prompt.OptionSuggestionBGColor(prompt.Black), + prompt.OptionSuggestionTextColor(prompt.Green), + prompt.OptionDescriptionBGColor(prompt.Black), + prompt.OptionDescriptionTextColor(prompt.White), + prompt.OptionLivePrefix(livePrefix), + ) + client.RegisterFlagBinder(func(fs *pflag.FlagSet, namer naming.Namer) { fs.StringVar(&username, namer("auth-username"), "", "username for gRPC basic authentication") fs.StringVar(&password, namer("auth-password"), "", "password for gRPC basic authentication") }) + sh.Flags().StringVar(&serverAddr, "server-addr", defaultServerAddr, "gRPC server address") + sh.Flags().StringVar(&username, "auth-username", "", + "username for gRPC basic authentication") + + sh.Flags().StringVar(&password, "auth-password", "", + "username for gRPC basic authentication") + + sh.PreRun = func(_ *cobra.Command, _ []string) { + cls() + cmd.PrintInfoMsgf("Welcome to PactusBlockchain shell\n\n- Home: https//pactus.org\n- " + + "Docs: https://docs.pactus.org") + cmd.PrintLine() + _prefix = fmt.Sprintf("pactus@%s > ", serverAddr) + } + + sh.PersistentPreRun = func(cmd *cobra.Command, _ []string) { + setAuthContext(cmd, username, password) + } + + rootCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) { + setAuthContext(cmd, username, password) + } + changeDefaultParameters := func(c *cobra.Command) *cobra.Command { _ = c.PersistentFlags().Lookup("server-addr").Value.Set(defaultServerAddr) c.PersistentFlags().Lookup("server-addr").DefValue = defaultServerAddr @@ -45,24 +82,43 @@ func main() { return c } - rootCmd.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error { - if username != "" && password != "" { - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - md := metadata.Pairs("authorization", "Basic "+auth) - ctx := metadata.NewOutgoingContext(cmd.Context(), md) - cmd.SetContext(ctx) - } - - return nil - } - rootCmd.AddCommand(changeDefaultParameters(pb.BlockchainClientCommand())) rootCmd.AddCommand(changeDefaultParameters(pb.NetworkClientCommand())) rootCmd.AddCommand(changeDefaultParameters(pb.TransactionClientCommand())) rootCmd.AddCommand(changeDefaultParameters(pb.WalletClientCommand())) + rootCmd.AddCommand(clearScreen()) + rootCmd.AddCommand(sh) err := rootCmd.Execute() if err != nil { cmd.PrintErrorMsgf("%s", err) } } + +func livePrefix() (string, bool) { + return _prefix, true +} + +func clearScreen() *cobra.Command { + return &cobra.Command{ + Use: "clear", + Short: "clear screen", + Run: func(_ *cobra.Command, _ []string) { + cls() + }, + } +} + +func cls() { + screen.MoveTopLeft() + screen.Clear() +} + +func setAuthContext(c *cobra.Command, username, password string) { + if username != "" && password != "" { + auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) + md := metadata.Pairs("authorization", "Basic "+auth) + ctx := metadata.NewOutgoingContext(c.Context(), md) + c.SetContext(ctx) + } +} diff --git a/go.mod b/go.mod index e30fcd5a7..1102af5d7 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,10 @@ go 1.22.2 require ( github.com/NathanBaulch/protoc-gen-cobra v1.2.1 github.com/beevik/ntp v1.4.3 + github.com/c-bata/go-prompt v0.2.6 github.com/fxamacker/cbor/v2 v2.7.0 github.com/gofrs/flock v0.9.0 + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.5.2 github.com/gorilla/mux v1.8.1 @@ -14,6 +16,8 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/hashicorp/golang-lru/v2 v2.0.7 + github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3 + github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 github.com/kilic/bls12-381 v0.1.0 github.com/libp2p/go-libp2p v0.35.1 github.com/libp2p/go-libp2p-kad-dht v0.25.2 @@ -25,6 +29,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.19.1 github.com/rs/zerolog v1.33.0 + github.com/schollz/progressbar/v3 v3.14.4 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 @@ -33,6 +38,7 @@ require ( go.nanomsg.org/mangos/v3 v3.4.2 golang.org/x/crypto v0.24.0 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 + golang.org/x/term v0.22.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 gopkg.in/natefinch/lumberjack.v2 v2.2.1 @@ -80,7 +86,6 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect - github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/koron/go-ssdp v0.0.4 // indirect @@ -100,6 +105,8 @@ require ( github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-tty v0.0.3 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect @@ -137,6 +144,7 @@ require ( github.com/pion/transport/v2 v2.2.5 // indirect github.com/pion/turn/v2 v2.1.6 // indirect github.com/pion/webrtc/v3 v3.2.43 // indirect + github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -147,7 +155,6 @@ require ( github.com/quic-go/webtransport-go v0.8.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/schollz/progressbar/v3 v3.14.4 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect @@ -165,7 +172,6 @@ require ( golang.org/x/net v0.26.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/tools v0.22.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect diff --git a/go.sum b/go.sum index 7ae004190..22c537394 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= +github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -158,6 +160,8 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20240625030939-27f56978b8b0 h1:e+8XbKB6IMn8A4OAyZccO4pYfB3s7bt6azNIPE7AnPg= github.com/google/pprof v0.0.0-20240625030939-27f56978b8b0/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -196,6 +200,8 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3 h1:fO9A67/izFYFYky7l1pDP5Dr0BTCRkaQJUG6Jm5ehsk= +github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3/go.mod h1:Ey4uAp+LvIl+s5jRbOHLcZpUDnkjLBROl15fZLwPlTM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/boxo v0.21.0 h1:XpGXb+TQQ0IUdYaeAxGzWjSs6ow/Lce148A/2IbRDVE= @@ -290,13 +296,23 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= +github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -424,6 +440,8 @@ github.com/pion/webrtc/v3 v3.2.43/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/Ogp github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= +github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= @@ -662,18 +680,24 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -702,8 +726,6 @@ golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -792,8 +814,6 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/util/shell/shell.go b/util/shell/shell.go new file mode 100644 index 000000000..a94c44aeb --- /dev/null +++ b/util/shell/shell.go @@ -0,0 +1,250 @@ +package shell + +import ( + "bytes" + "fmt" + "os" + "sort" + "strings" + + "github.com/c-bata/go-prompt" + "github.com/google/shlex" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "golang.org/x/term" +) + +type lexer struct { + root *cobra.Command + refresh func() *cobra.Command + cache map[string][]prompt.Suggest + stdin *term.State +} + +// New creates a Cobra CLI command named "shell" which runs an interactive shell prompt for the root command. +func New(root *cobra.Command, refresh func() *cobra.Command, opts ...prompt.Option) *cobra.Command { + sh := &lexer{ + root: root, + refresh: refresh, + cache: make(map[string][]prompt.Suggest), + } + + prefix := fmt.Sprintf("> %s ", root.Name()) + opts = append(opts, prompt.OptionPrefix(prefix), prompt.OptionShowCompletionAtStart()) + + return &cobra.Command{ + Use: "shell", + Short: "Start an interactive shell.", + Run: func(cmd *cobra.Command, _ []string) { + sh.saveStdin() + + sh.editCommandTree(cmd) + prompt.New(sh.executor, sh.completer, opts...).Run() + + sh.restoreStdin() + }, + } +} + +func (s *lexer) editCommandTree(shell *cobra.Command) { + s.root.RemoveCommand(shell) + + // Hide the "completion" command + if cmd, _, err := s.root.Find([]string{"completion"}); err == nil { + // TODO: Remove this command + cmd.Hidden = true + } + + s.root.AddCommand(&cobra.Command{ + Use: "exit", + Short: "Exit the interactive shell.", + Run: func(*cobra.Command, []string) { + // TODO: Exit cleanly without help from the os package + os.Exit(0) + }, + }) + + initDefaultHelpFlag(s.root) +} + +func initDefaultHelpFlag(cmd *cobra.Command) { + cmd.InitDefaultHelpFlag() + + for _, subcommand := range cmd.Commands() { + initDefaultHelpFlag(subcommand) + } +} + +func (s *lexer) saveStdin() { + state, err := term.GetState(int(os.Stdin.Fd())) + if err != nil { + return + } + s.stdin = state +} + +func (s *lexer) executor(line string) { + // Allow command to read from stdin + s.restoreStdin() + + args, _ := shlex.Split(line) + _ = execute(s.root, args) + + if s.refresh != nil { + s.root = s.refresh() + s.editCommandTree(s.root) + } else { + if cmd, _, err := s.root.Find(args); err == nil { + cmd.Flags().VisitAll(func(flag *pflag.Flag) { + flag.Changed = false + }) + } + } + + s.cache = make(map[string][]prompt.Suggest) +} + +func (s *lexer) restoreStdin() { + if s.stdin != nil { + _ = term.Restore(int(os.Stdin.Fd()), s.stdin) + } +} + +func (s *lexer) completer(d prompt.Document) []prompt.Suggest { + args, err := buildCompletionArgs(d.CurrentLine()) + if err != nil { + return nil + } + + if !isFlag(args[len(args)-1]) { + // Clear partial strings to generate all possible completions + args[len(args)-1] = "" + } + key := strings.Join(args, " ") + + suggestions, ok := s.cache[key] + if !ok { + out, err := readCommandOutput(s.root, args) + if err != nil { + return nil + } + suggestions = parseSuggestions(out) + s.cache[key] = suggestions + } + + return prompt.FilterHasPrefix(suggestions, d.GetWordBeforeCursor(), true) +} + +func buildCompletionArgs(input string) ([]string, error) { + args, err := shlex.Split(input) + + args = append([]string{"__complete"}, args...) + if input == "" || input[len(input)-1] == ' ' { + args = append(args, "") + } + + return args, err +} + +func readCommandOutput(cmd *cobra.Command, args []string) (string, error) { + buf := new(bytes.Buffer) + + stdout := cmd.OutOrStdout() + stderr := os.Stderr + + cmd.SetOut(buf) + _, os.Stderr, _ = os.Pipe() + + err := execute(cmd, args) + + cmd.SetOut(stdout) + os.Stderr = stderr + + return buf.String(), err +} + +func execute(cmd *cobra.Command, args []string) error { + if c, _, err := cmd.Find(args); err == nil { + // Reset flag values between runs due to a limitation in Cobra + c.Flags().VisitAll(func(flag *pflag.Flag) { + if val, ok := flag.Value.(pflag.SliceValue); ok { + _ = val.Replace([]string{}) + } else { + _ = flag.Value.Set(flag.DefValue) + } + + _ = c.Flags().SetAnnotation(flag.Name, cobra.BashCompOneRequiredFlag, []string{"false"}) + }) + + c.InitDefaultHelpFlag() + } + + cmd.SetArgs(args) + + return cmd.Execute() +} + +func parseSuggestions(out string) []prompt.Suggest { + suggestions := make([]prompt.Suggest, 0) + + x := strings.Split(out, "\n") + if len(x) < 2 { + return nil + } + + for _, line := range x[:len(x)-2] { + l := strings.SplitN(line, "\t", 2) + + if isShorthandFlag(l[0]) { + continue + } + + suggestion := prompt.Suggest{Text: escapeSpecialCharacters(l[0])} + if len(l) > 1 { + suggestion.Description = l[1] + } + + suggestions = append(suggestions, suggestion) + } + + sort.Slice(suggestions, func(i, j int) bool { + it := suggestions[i].Text + jt := suggestions[j].Text + + if isFlag(it) && isFlag(jt) { + return it < jt + } + + if isFlag(it) { + return false + } + + if isFlag(jt) { + return true + } + + return it < jt + }) + + return suggestions +} + +func escapeSpecialCharacters(val string) string { + for _, c := range []string{`\`, `"`, "$", "`", "!"} { + val = strings.ReplaceAll(val, c, `\`+c) + } + + if strings.ContainsAny(val, " #&*;<>?[]|~") { + val = fmt.Sprintf("%q", val) + } + + return val +} + +func isFlag(arg string) bool { + return strings.HasPrefix(arg, "-") +} + +func isShorthandFlag(arg string) bool { + return isFlag(arg) && !strings.HasPrefix(arg, "--") +} diff --git a/util/shell/shell_test.go b/util/shell/shell_test.go new file mode 100644 index 000000000..dfce17551 --- /dev/null +++ b/util/shell/shell_test.go @@ -0,0 +1,150 @@ +package shell + +import ( + "errors" + "testing" + + "github.com/c-bata/go-prompt" + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +func TestBuildCompletionArgs_Empty(t *testing.T) { + args, err := buildCompletionArgs("") + require.NoError(t, err) + + expected := []string{"__complete", ""} + require.Equal(t, expected, args) +} + +func TestBuildCompletionArgs_CurrentArg(t *testing.T) { + args, err := buildCompletionArgs("a b") + require.NoError(t, err) + + expected := []string{"__complete", "a", "b"} + require.Equal(t, expected, args) +} + +func TestBuildCompletionArgs_MultiwordString(t *testing.T) { + args, err := buildCompletionArgs(`a "b c"`) + require.NoError(t, err) + + expected := []string{"__complete", "a", "b c"} + require.Equal(t, expected, args) +} + +func TestBuildCompletionArgs_NextArg(t *testing.T) { + args, err := buildCompletionArgs("a b ") + require.NoError(t, err) + + expected := []string{"__complete", "a", "b", ""} + require.Equal(t, expected, args) +} + +func TestReadCommandOutput_Stdout(t *testing.T) { + cmd := &cobra.Command{ + Use: "command", + Run: func(cmd *cobra.Command, _ []string) { + cmd.Print("out") + }, + } + + out, err := readCommandOutput(cmd, []string{}) + require.NoError(t, err) + require.Equal(t, "out", out) +} + +func TestReadCommandOutput_Stderr(t *testing.T) { + cmd := &cobra.Command{ + Use: "command", + Run: func(cmd *cobra.Command, _ []string) { + cmd.PrintErr("out") + }, + } + + out, err := readCommandOutput(cmd, []string{}) + require.NoError(t, err) + require.Empty(t, out) +} + +func TestReadCommandOutput_Err(t *testing.T) { + cmd := &cobra.Command{ + Use: "command", + RunE: func(_ *cobra.Command, _ []string) error { + return errors.New("err") + }, + } + + _, err := readCommandOutput(cmd, []string{}) + require.Error(t, err) +} + +func TestParseSuggestions_WithDescription(t *testing.T) { + out := `command-with-description description +:4 +Completion ended with directive: ShellCompDirectiveNoFileComp` + expected := []prompt.Suggest{{Text: "command-with-description", Description: "description"}} + require.Equal(t, expected, parseSuggestions(out)) +} + +func TestParseSuggestions_WithoutDescription(t *testing.T) { + out := `command-without-description +:4 +Completion ended with directive: ShellCompDirectiveNoFileComp` + expected := []prompt.Suggest{{Text: "command-without-description"}} + require.Equal(t, expected, parseSuggestions(out)) +} + +func TestParseSuggestions_HideShorthandFlags(t *testing.T) { + out := `--flag A flag. +-f A flag. +:4 +Completion ended with directive: ShellCompDirectiveNoFileComp` + expected := []prompt.Suggest{{Text: "--flag", Description: "A flag."}} + require.Equal(t, expected, parseSuggestions(out)) +} + +func TestParseSuggestions_Sort(t *testing.T) { + out := `b +a +:4 +Completion ended with directive: ShellCompDirectiveNoFileComp` + expected := []prompt.Suggest{{Text: "a"}, {Text: "b"}} + require.Equal(t, expected, parseSuggestions(out)) +} + +func TestEscapeSpecialCharacters_Spaces(t *testing.T) { + require.Equal(t, `"string with spaces"`, escapeSpecialCharacters("string with spaces")) +} + +func TestEscapeSpecialCharacters_All(t *testing.T) { + require.Equal(t, "\\\\\\\"\\$\\`\\!", escapeSpecialCharacters("\\\"$`!")) +} + +func TestEditCommandTree_RemoveShell(t *testing.T) { + root := &cobra.Command{} + sh := &cobra.Command{Use: "lexer"} + root.AddCommand(sh) + + s := &lexer{root: root} + s.editCommandTree(sh) + require.False(t, hasSubcommand(root, "lexer")) +} + +func TestEditCommandTree_AddExit(t *testing.T) { + root := &cobra.Command{} + + s := &lexer{root: root} + s.editCommandTree(nil) + require.True(t, hasSubcommand(root, "exit")) +} + +func hasSubcommand(cmd *cobra.Command, name string) bool { + for _, subcommand := range cmd.Commands() { + if subcommand.Name() == name { + return true + } + } + + return false +} From 98b228e5ace087e021b91373f0838983c2162649 Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Wed, 7 Aug 2024 20:25:47 +0330 Subject: [PATCH 04/25] fix(grpc): add example json-rpc in generated doc (#1461) --- Makefile | 1 - www/grpc/buf/json-rpc-md.tmpl | 52 +++++++++++++++++- www/grpc/gen/docs/grpc.md | 2 +- www/grpc/gen/docs/json-rpc.md | 54 ++++++++++++++++++- www/grpc/gen/go/blockchain.pb.go | 2 +- .../blockchain/BlockchainOuterClass.java | 10 ++-- www/grpc/gen/rust/pactus.rs | 2 +- www/grpc/swagger-ui/pactus.swagger.json | 2 +- 8 files changed, 112 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 28d1f8642..e0d85b568 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,6 @@ devtools: go install mvdan.cc/gofumpt@latest go install github.com/rakyll/statik@v0.1.7 go install github.com/pacviewer/jrpc-gateway/protoc-gen-jrpc-gateway@v0.3.2 - go install github.com/pacviewer/jrpc-gateway/protoc-gen-jrpc-doc/cmd/protoc-gen-jrpc-doc@v0.1.7 ######################################## ### Building diff --git a/www/grpc/buf/json-rpc-md.tmpl b/www/grpc/buf/json-rpc-md.tmpl index aef588647..bf2f37433 100644 --- a/www/grpc/buf/json-rpc-md.tmpl +++ b/www/grpc/buf/json-rpc-md.tmpl @@ -10,7 +10,57 @@ All the amounts and values in gRPC endpoints are in NanoPAC units, which are atomic and the smallest unit in the Pactus blockchain. Each PAC is equivalent to 1,000,000,000 or 109 NanoPACs. -

JSON-RPC Services

+## Example + +To call JSON-RPC methods, you need to create the JSON-RPC request: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "pactus.network.get_node_info", + "params": {} +} +``` + +> Make sure you always add the `params` field, even if no parameters are needed, and ensure you use curly braces. + +Then you use the `curl` command to send the request to the node: + +```bash +curl --location 'http://localhost:8545/' \ +--header 'Content-Type: application/json' \ +--data '{ + "jsonrpc": "2.0", + "id": 1, + "method": "pactus.network.get_node_info", + "params": {} +}' +``` + +> Before sending the request, you need to enable the JSON-RPC service inside the +> [configuration](/get-started/configuration/). + +### Using Basic Auth + +If you have enabled the [gRPC Basic Authentication](/tutorials/grpc-sign-transactions/), +then you need to set the `Authorization` header. + +```bash +curl --location 'http://localhost:8545/' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' \ +--data '{ + "jsonrpc": "2.0", + "id": 1, + "method": "pactus.blockchain.get_account", + "params": { + "address": "pc1z2r0fmu8sg2ffa0tgrr08gnefcxl2kq7wvquf8z" + } +}' +``` + +

JSON-RPC Methods

    diff --git a/www/grpc/gen/docs/grpc.md b/www/grpc/gen/docs/grpc.md index f0250feec..4a5202701 100644 --- a/www/grpc/gen/docs/grpc.md +++ b/www/grpc/gen/docs/grpc.md @@ -1402,7 +1402,7 @@ Message has no fields. last_block_time int64 - The last block time as timestamp + Timestamp of the last block in Unix format diff --git a/www/grpc/gen/docs/json-rpc.md b/www/grpc/gen/docs/json-rpc.md index dd4ce6fec..af07bb94d 100644 --- a/www/grpc/gen/docs/json-rpc.md +++ b/www/grpc/gen/docs/json-rpc.md @@ -10,7 +10,57 @@ All the amounts and values in gRPC endpoints are in NanoPAC units, which are atomic and the smallest unit in the Pactus blockchain. Each PAC is equivalent to 1,000,000,000 or 109 NanoPACs. -

    JSON-RPC Services

    +## Example + +To call JSON-RPC methods, you need to create the JSON-RPC request: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "pactus.network.get_node_info", + "params": {} +} +``` + +> Make sure you always add the `params` field, even if no parameters are needed, and ensure you use curly braces. + +Then you use the `curl` command to send the request to the node: + +```bash +curl --location 'http://localhost:8545/' \ +--header 'Content-Type: application/json' \ +--data '{ + "jsonrpc": "2.0", + "id": 1, + "method": "pactus.network.get_node_info", + "params": {} +}' +``` + +> Before sending the request, you need to enable the JSON-RPC service inside the +> [configuration](/get-started/configuration/). + +### Using Basic Auth + +If you have enabled the [gRPC Basic Authentication](/tutorials/grpc-sign-transactions/), +then you need to set the `Authorization` header. + +```bash +curl --location 'http://localhost:8545/' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' \ +--data '{ + "jsonrpc": "2.0", + "id": 1, + "method": "pactus.blockchain.get_account", + "params": { + "address": "pc1z2r0fmu8sg2ffa0tgrr08gnefcxl2kq7wvquf8z" + } +}' +``` + +

    JSON-RPC Methods

      @@ -1403,7 +1453,7 @@ Parameters has no fields. last_block_time numeric - The last block time as timestamp + Timestamp of the last block in Unix format diff --git a/www/grpc/gen/go/blockchain.pb.go b/www/grpc/gen/go/blockchain.pb.go index a13c249ca..54adbf252 100644 --- a/www/grpc/gen/go/blockchain.pb.go +++ b/www/grpc/gen/go/blockchain.pb.go @@ -982,7 +982,7 @@ type GetBlockchainInfoResponse struct { IsPruned bool `protobuf:"varint,8,opt,name=is_pruned,json=isPruned,proto3" json:"is_pruned,omitempty"` // Lowest-height block stored (only present if pruning is enabled) PruningHeight uint32 `protobuf:"varint,9,opt,name=pruning_height,json=pruningHeight,proto3" json:"pruning_height,omitempty"` - // The last block time as timestamp + // Timestamp of the last block in Unix format LastBlockTime int64 `protobuf:"varint,10,opt,name=last_block_time,json=lastBlockTime,proto3" json:"last_block_time,omitempty"` } diff --git a/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java b/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java index d8e174538..efb543008 100644 --- a/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java +++ b/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java @@ -10975,7 +10975,7 @@ pactus.blockchain.BlockchainOuterClass.ValidatorInfoOrBuilder getCommitteeValida /** *
      -     * The last block time as timestamp
      +     * Timestamp of the last block in Unix format
            * 
      * * int64 last_block_time = 10 [json_name = "lastBlockTime"]; @@ -11244,7 +11244,7 @@ public int getPruningHeight() { private long lastBlockTime_; /** *
      -     * The last block time as timestamp
      +     * Timestamp of the last block in Unix format
            * 
      * * int64 last_block_time = 10 [json_name = "lastBlockTime"]; @@ -12536,7 +12536,7 @@ public Builder clearPruningHeight() { private long lastBlockTime_ ; /** *
      -       * The last block time as timestamp
      +       * Timestamp of the last block in Unix format
              * 
      * * int64 last_block_time = 10 [json_name = "lastBlockTime"]; @@ -12548,7 +12548,7 @@ public long getLastBlockTime() { } /** *
      -       * The last block time as timestamp
      +       * Timestamp of the last block in Unix format
              * 
      * * int64 last_block_time = 10 [json_name = "lastBlockTime"]; @@ -12563,7 +12563,7 @@ public Builder setLastBlockTime(long value) { } /** *
      -       * The last block time as timestamp
      +       * Timestamp of the last block in Unix format
              * 
      * * int64 last_block_time = 10 [json_name = "lastBlockTime"]; diff --git a/www/grpc/gen/rust/pactus.rs b/www/grpc/gen/rust/pactus.rs index 36ce81831..897e4a1b0 100644 --- a/www/grpc/gen/rust/pactus.rs +++ b/www/grpc/gen/rust/pactus.rs @@ -532,7 +532,7 @@ pub struct GetBlockchainInfoResponse { /// Lowest-height block stored (only present if pruning is enabled) #[prost(uint32, tag="9")] pub pruning_height: u32, - /// The last block time as timestamp + /// Timestamp of the last block in Unix format #[prost(int64, tag="10")] pub last_block_time: i64, } diff --git a/www/grpc/swagger-ui/pactus.swagger.json b/www/grpc/swagger-ui/pactus.swagger.json index a5f84b7c6..c7a3d6e1e 100644 --- a/www/grpc/swagger-ui/pactus.swagger.json +++ b/www/grpc/swagger-ui/pactus.swagger.json @@ -1628,7 +1628,7 @@ "lastBlockTime": { "type": "string", "format": "int64", - "title": "The last block time as timestamp" + "title": "Timestamp of the last block in Unix format" } }, "description": "Message containing the response with general blockchain information." From dcdb8bf9578ed13ae8853abef32df7710b2a367e Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Fri, 9 Aug 2024 18:10:39 +0330 Subject: [PATCH 05/25] fix(gtk): width size of listbox and download button (#1434) --- cmd/gtk/startup_assistant.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/gtk/startup_assistant.go b/cmd/gtk/startup_assistant.go index 05533097d..a4a83620c 100644 --- a/cmd/gtk/startup_assistant.go +++ b/cmd/gtk/startup_assistant.go @@ -182,13 +182,13 @@ func startupAssistant(workingDir string, chainType genesis.ChainType) bool { fatalErrorCheck(err) setMargin(listBox, 5, 5, 1, 1) listBox.SetHAlign(gtk.ALIGN_CENTER) - listBox.SetSizeRequest(600, -1) + listBox.SetSizeRequest(700, -1) ssDLBtn, err := gtk.ButtonNewWithLabel("⏬ Download") fatalErrorCheck(err) setMargin(ssDLBtn, 10, 5, 1, 1) ssDLBtn.SetHAlign(gtk.ALIGN_CENTER) - ssDLBtn.SetSizeRequest(600, -1) + ssDLBtn.SetSizeRequest(700, -1) ssPBLabel, err := gtk.LabelNew("") fatalErrorCheck(err) From aee4482f35c93e9c7bc79e188afb157a99257209 Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Sun, 11 Aug 2024 18:15:53 +0330 Subject: [PATCH 06/25] fix(util): chunked download to improve download speed (#1459) --- util/downloader/chunk.go | 31 ++++++ util/downloader/chunk_test.go | 112 +++++++++++++++++++ util/downloader/downloader.go | 202 ++++++++++++++++------------------ util/downloader/errors.go | 18 +++ 4 files changed, 257 insertions(+), 106 deletions(-) create mode 100644 util/downloader/chunk.go create mode 100644 util/downloader/chunk_test.go create mode 100644 util/downloader/errors.go diff --git a/util/downloader/chunk.go b/util/downloader/chunk.go new file mode 100644 index 000000000..1d9446c95 --- /dev/null +++ b/util/downloader/chunk.go @@ -0,0 +1,31 @@ +package downloader + +import "fmt" + +type chunk struct { + start, end int64 +} + +func createChunks(contentLength, totalChunks int64) []*chunk { + chunks := make([]*chunk, 0, totalChunks) + chunkSize := contentLength / totalChunks + for i := int64(0); i < totalChunks; i++ { + start := i * chunkSize + end := start + chunkSize - 1 + // adjust the end for the last chunk + if i == totalChunks-1 { + end = contentLength - 1 + } + chunks = append(chunks, &chunk{start: start, end: end}) + } + + return chunks +} + +func (c *chunk) rangeHeader() string { + return fmt.Sprintf("bytes=%d-%d", c.start, c.end) +} + +func (c *chunk) size() int64 { + return (c.end + 1) - c.start +} diff --git a/util/downloader/chunk_test.go b/util/downloader/chunk_test.go new file mode 100644 index 000000000..efdb7f85d --- /dev/null +++ b/util/downloader/chunk_test.go @@ -0,0 +1,112 @@ +package downloader + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreateChunks(t *testing.T) { + tests := []struct { + contentLength int64 + totalChunks int64 + expected []*chunk + }{ + { + contentLength: 181403648, + totalChunks: 16, + expected: []*chunk{ + {start: 0, end: 11337727}, + {start: 11337728, end: 22675455}, + {start: 22675456, end: 34013183}, + {start: 34013184, end: 45350911}, + {start: 45350912, end: 56688639}, + {start: 56688640, end: 68026367}, + {start: 68026368, end: 79364095}, + {start: 79364096, end: 90701823}, + {start: 90701824, end: 102039551}, + {start: 102039552, end: 113377279}, + {start: 113377280, end: 124715007}, + {start: 124715008, end: 136052735}, + {start: 136052736, end: 147390463}, + {start: 147390464, end: 158728191}, + {start: 158728192, end: 170065919}, + {start: 170065920, end: 181403647}, + }, + }, + { + contentLength: 10, + totalChunks: 3, + expected: []*chunk{ + {start: 0, end: 2}, + {start: 3, end: 5}, + {start: 6, end: 9}, + }, + }, + { + contentLength: 10, + totalChunks: 1, + expected: []*chunk{ + {start: 0, end: 9}, + }, + }, + { + contentLength: 0, + totalChunks: 1, + expected: []*chunk{ + {start: 0, end: -1}, + }, + }, + } + + for _, tt := range tests { + actual := createChunks(tt.contentLength, tt.totalChunks) + assert.Equal(t, tt.expected, actual) + } +} + +func TestChunkRangeHeader(t *testing.T) { + tests := []struct { + chunk chunk + expected string + }{ + { + chunk: chunk{start: 0, end: 499}, + expected: "bytes=0-499", + }, + { + chunk: chunk{start: 500, end: 999}, + expected: "bytes=500-999", + }, + } + + for _, tt := range tests { + actual := tt.chunk.rangeHeader() + assert.Equal(t, tt.expected, actual) + } +} + +func TestChunkSize(t *testing.T) { + tests := []struct { + chunk chunk + expected int64 + }{ + { + chunk: chunk{start: 0, end: 499}, + expected: 500, + }, + { + chunk: chunk{start: 500, end: 999}, + expected: 500, + }, + { + chunk: chunk{start: 0, end: 0}, + expected: 1, + }, + } + + for _, tt := range tests { + actual := tt.chunk.size() + assert.Equal(t, tt.expected, actual) + } +} diff --git a/util/downloader/downloader.go b/util/downloader/downloader.go index ee842bd89..06e2d2567 100644 --- a/util/downloader/downloader.go +++ b/util/downloader/downloader.go @@ -6,24 +6,16 @@ import ( "encoding/hex" "errors" "fmt" - "hash" "io" "net/http" "os" "path/filepath" + "sync" ) -var ( - ErrHeaderRequest = errors.New("request header error") - ErrSHA256Mismatch = errors.New("sha256 mismatch") - ErrCreateDir = errors.New("create dir error") - ErrInvalidFilePath = errors.New("file path is a directory, not a file") - ErrGetFileInfo = errors.New("get file info error") - ErrCopyExistsFileData = errors.New("error copying existing file data") - ErrDoRequest = errors.New("error doing request") - ErrFileWriting = errors.New("error writing file") - ErrNewRequest = errors.New("error creating request") - ErrOpenFileExists = errors.New("error opening existing file") +const ( + _defaultConcurrencyPerChunk = 16 + _defaultMinSizeForChunk = 1 << 20 ) type Downloader struct { @@ -35,6 +27,11 @@ type Downloader struct { fileName string statsCh chan Stats errCh chan error + + chunks []*chunk + + mu sync.Mutex + downloaded int64 } type Stats struct { @@ -56,6 +53,7 @@ func New(url, filePath, sha256Sum string, opts ...Option) *Downloader { url: url, filePath: filePath, sha256Sum: sha256Sum, + chunks: make([]*chunk, 0, _defaultConcurrencyPerChunk), statsCh: make(chan Stats), errCh: make(chan error, 1), } @@ -96,7 +94,7 @@ func (d *Downloader) download(ctx context.Context) { return } - out, err := d.openFile() + out, err := os.OpenFile(d.filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600) if err != nil { d.handleError(err) @@ -106,13 +104,25 @@ func (d *Downloader) download(ctx context.Context) { _ = out.Close() }() - if err := d.validateExistingFile(out, &stats); err != nil { - d.handleError(err) + d.statsCh <- stats - return + var wg sync.WaitGroup + for _, c := range d.chunks { + wg.Add(1) + go func(c *chunk) { + defer wg.Done() + err := d.downloadChunkWithContext(ctx, out, c, stats.TotalSize) + if err != nil { + d.handleError(err) + + return + } + }(c) } - if err := d.downloadFile(ctx, out, &stats); err != nil { + wg.Wait() + + if err := d.finalizeDownload(&stats); err != nil { d.handleError(err) } } @@ -120,12 +130,12 @@ func (d *Downloader) download(ctx context.Context) { func (d *Downloader) getHeader(ctx context.Context) (Stats, error) { req, err := http.NewRequestWithContext(ctx, http.MethodHead, d.url, http.NoBody) if err != nil { - return Stats{}, ErrHeaderRequest + return Stats{}, &Error{Message: "failed to create new request for get header", Reason: err} } resp, err := d.client.Do(req) if err != nil { - return Stats{}, ErrHeaderRequest + return Stats{}, &Error{Message: "failed to do request get header", Reason: err} } defer func() { @@ -134,6 +144,15 @@ func (d *Downloader) getHeader(ctx context.Context) (Stats, error) { d.fileType = resp.Header.Get("Content-Type") + if resp.ContentLength > _defaultMinSizeForChunk { + d.chunks = createChunks(resp.ContentLength, _defaultConcurrencyPerChunk) + } else { + d.chunks = append(d.chunks, &chunk{ + start: 0, + end: resp.ContentLength, + }) + } + return Stats{ TotalSize: resp.ContentLength, }, nil @@ -142,126 +161,97 @@ func (d *Downloader) getHeader(ctx context.Context) (Stats, error) { func (d *Downloader) createDir() error { dir := filepath.Dir(d.filePath) if err := os.MkdirAll(dir, 0o750); err != nil { - return ErrCreateDir + return &Error{Message: "failed to create file path directory", Reason: err} } return nil } -func (d *Downloader) openFile() (*os.File, error) { - fileInfo, err := os.Stat(d.filePath) - if err == nil && fileInfo.IsDir() { - return nil, ErrInvalidFilePath - } - - return os.OpenFile(d.filePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600) -} - -func (*Downloader) validateExistingFile(out *os.File, stats *Stats) error { - fileInfo, err := out.Stat() - if err != nil { - return ErrGetFileInfo - } - stats.Downloaded = fileInfo.Size() - - return nil -} - -func (d *Downloader) downloadFile(ctx context.Context, out *os.File, stats *Stats) error { - req, err := d.createRequest(ctx, stats.Downloaded) +func (d *Downloader) downloadChunkWithContext(ctx context.Context, out *os.File, c *chunk, totalSize int64) error { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, d.url, http.NoBody) if err != nil { - return err + return &Error{Message: "failed to create new request for download chunk", Reason: err} } + req.Header.Set("Range", c.rangeHeader()) resp, err := d.client.Do(req) if err != nil { - return ErrDoRequest + return &Error{Message: "failed to do request download chunk", Reason: err} } defer func() { _ = resp.Body.Close() }() - buffer := make([]byte, 32*1024) - hasher := sha256.New() - - if err := d.updateHasherWithExistingData(stats.Downloaded, hasher); err != nil { - return err - } - - return d.writeToFile(ctx, resp, out, buffer, hasher, stats) -} - -func (d *Downloader) createRequest(ctx context.Context, downloaded int64) (*http.Request, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, d.url, http.NoBody) - if err != nil { - return nil, ErrNewRequest - } - if downloaded > 0 { - req.Header.Set("Range", fmt.Sprintf("bytes=%d-", downloaded)) + if resp.StatusCode != http.StatusPartialContent && resp.StatusCode != http.StatusOK { + return &Error{ + Message: "response has invalid status code", + Reason: fmt.Errorf("got http response %s from %s: %w", resp.Status, d.url, err), + } } - return req, nil -} - -func (d *Downloader) updateHasherWithExistingData(downloaded int64, hasher io.Writer) error { - if downloaded > 0 { - existingFile, err := os.Open(d.filePath) - if err != nil { - return ErrOpenFileExists + buf := make([]byte, 32*1024) // 32KB buffer for reading the response body + offset := c.start + for { + n, err := resp.Body.Read(buf) + if n > 0 { + d.mu.Lock() + for written := 0; written < n; { + w, err := out.WriteAt(buf[written:n], offset+int64(written)) + if err != nil { + d.mu.Unlock() + + return &Error{Message: "failed write data into file", Reason: err} + } + written += w + } + offset += int64(n) + d.downloaded += int64(n) + d.updateStats(d.downloaded, totalSize) + d.mu.Unlock() } - defer func() { - _ = existingFile.Close() - }() + if err != nil { + // if error is io.EOF stop write for loop response body. + if errors.Is(err, io.EOF) { + break + } - if _, err := io.CopyN(hasher, existingFile, downloaded); err != nil { - return ErrCopyExistsFileData + return &Error{Message: "error read body download chunk", Reason: err} } } return nil } -func (d *Downloader) writeToFile(ctx context.Context, resp *http.Response, out *os.File, buffer []byte, - hasher hash.Hash, stats *Stats, -) error { - for { - select { - case <-ctx.Done(): - d.stop() - - return ctx.Err() - default: - n, err := resp.Body.Read(buffer) - if n > 0 { - if _, err := out.Write(buffer[:n]); err != nil { - return ErrFileWriting - } - - if _, err := hasher.Write(buffer[:n]); err != nil { - return ErrFileWriting - } +func (d *Downloader) updateStats(downloaded, totalSize int64) { + stats := Stats{ + Downloaded: downloaded, + TotalSize: totalSize, + Percent: float64(downloaded) / float64(totalSize) * 100, + } + d.statsCh <- stats +} - stats.Downloaded += int64(n) - stats.Percent = float64(stats.Downloaded) / float64(stats.TotalSize) * 100 - d.statsCh <- *stats - } - if err != nil { - if err == io.EOF { - return d.finalizeDownload(hasher, stats) - } +func (d *Downloader) finalizeDownload(stats *Stats) error { + // Recalculate the hash by re-reading the entire file + out, err := os.Open(d.filePath) + if err != nil { + return &Error{Message: "failed to open file", Reason: err} + } + defer func() { + _ = out.Close() + }() - return fmt.Errorf("error reading response body: %w", err) - } - } + hasher := sha256.New() + if _, err := io.Copy(hasher, out); err != nil { + return &Error{Message: "failed copy file data to hasher for calculate hash", Reason: err} } -} -func (d *Downloader) finalizeDownload(hasher hash.Hash, stats *Stats) error { stats.Completed = true + stats.Percent = 100 sum := hex.EncodeToString(hasher.Sum(nil)) if sum != d.sha256Sum { - return ErrSHA256Mismatch + return &Error{Message: "sha256 mismatch", Reason: err} } d.statsCh <- *stats diff --git a/util/downloader/errors.go b/util/downloader/errors.go new file mode 100644 index 000000000..b11669bf5 --- /dev/null +++ b/util/downloader/errors.go @@ -0,0 +1,18 @@ +package downloader + +import ( + "fmt" +) + +type Error struct { + Message string + Reason error +} + +func (e *Error) Error() string { + return fmt.Sprintf("%s: %s", e.Message, e.Reason.Error()) +} + +func (e *Error) Unwrap() error { + return e.Reason +} From 9991001e3345955bc7666c745824059f47d1c6c3 Mon Sep 17 00:00:00 2001 From: K Date: Mon, 12 Aug 2024 15:07:58 +0330 Subject: [PATCH 07/25] feat(genesis): separating chain param from genesis param (#1463) --- cmd/cmd.go | 3 +- consensus/consensus_test.go | 3 +- genesis/genesis.go | 7 ++- .../param.go => genesis/genesis_params.go | 18 ++++---- genesis/genesis_test.go | 5 +-- genesis/testnet.json | 2 +- node/node_test.go | 3 +- sandbox/interface.go | 2 +- sandbox/mock.go | 5 ++- sandbox/sandbox.go | 2 +- sandbox/sandbox_test.go | 9 ++-- state/facade.go | 2 +- state/mock.go | 4 +- state/param/param.go | 45 +++++++++++++++++++ state/state.go | 8 ++-- state/state_test.go | 15 +++---- sync/firewall/firewall_test.go | 2 +- tests/main_test.go | 16 +++---- 18 files changed, 96 insertions(+), 55 deletions(-) rename types/param/param.go => genesis/genesis_params.go (86%) create mode 100644 state/param/param.go diff --git a/cmd/cmd.go b/cmd/cmd.go index e1cf0fbf9..76427b2cb 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -24,7 +24,6 @@ import ( "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/node" "github.com/pactus-project/pactus/types/account" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/wallet" @@ -440,7 +439,7 @@ func makeLocalGenesis(w wallet.Wallet) *genesis.Genesis { } // create genesis - params := param.DefaultParams() + params := genesis.DefaultGenesisParams() params.BlockVersion = 0 gen := genesis.MakeGenesis(util.RoundNow(60), accs, vals, params) diff --git a/consensus/consensus_test.go b/consensus/consensus_test.go index 416c40ce2..795d2d12d 100644 --- a/consensus/consensus_test.go +++ b/consensus/consensus_test.go @@ -16,7 +16,6 @@ import ( "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/certificate" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/proposal" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/validator" @@ -86,7 +85,7 @@ func setupWithSeed(t *testing.T, seed int64) *testData { acc := account.NewAccount(0) acc.AddToBalance(21 * 1e14) accs := map[crypto.Address]*account.Account{crypto.TreasuryAddress: acc} - params := param.DefaultParams() + params := genesis.DefaultGenesisParams() params.CommitteeSize = 4 // To prevent triggering timers before starting the tests and diff --git a/genesis/genesis.go b/genesis/genesis.go index a3d017489..9890d30a8 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -11,7 +11,6 @@ import ( "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util" ) @@ -57,7 +56,7 @@ type Genesis struct { type genesisData struct { GenesisTime time.Time `cbor:"1,keyasint" json:"genesis_time"` - Params *param.Params `cbor:"2,keyasint" json:"params"` + Params *GenesisParams `cbor:"2,keyasint" json:"params"` Accounts []genAccount `cbor:"3,keyasint" json:"accounts"` Validators []genValidator `cbor:"4,keyasint" json:"validators"` } @@ -72,7 +71,7 @@ func (gen *Genesis) GenesisTime() time.Time { return gen.data.GenesisTime } -func (gen *Genesis) Params() *param.Params { +func (gen *Genesis) Params() *GenesisParams { return gen.data.Params } @@ -124,7 +123,7 @@ func makeGenesisValidator(val *validator.Validator) genValidator { } func MakeGenesis(genesisTime time.Time, accounts map[crypto.Address]*account.Account, - validators []*validator.Validator, params *param.Params, + validators []*validator.Validator, params *GenesisParams, ) *Genesis { genAccs := make([]genAccount, len(accounts)) for addr, acc := range accounts { diff --git a/types/param/param.go b/genesis/genesis_params.go similarity index 86% rename from types/param/param.go rename to genesis/genesis_params.go index f4f319212..ed04f0d8f 100644 --- a/types/param/param.go +++ b/genesis/genesis_params.go @@ -1,4 +1,4 @@ -package param +package genesis import ( "time" @@ -6,7 +6,7 @@ import ( "github.com/pactus-project/pactus/types/amount" ) -type Params struct { +type GenesisParams struct { BlockVersion uint8 `cbor:"1,keyasint" json:"block_version"` BlockIntervalInSecond int `cbor:"2,keyasint" json:"block_interval_in_second"` CommitteeSize int `cbor:"3,keyasint" json:"committee_size"` @@ -22,8 +22,8 @@ type Params struct { MaximumStake amount.Amount `cbor:"13,keyasint" json:"maximum_stake"` } -func DefaultParams() *Params { - return &Params{ +func DefaultGenesisParams() *GenesisParams { + return &GenesisParams{ BlockVersion: 1, BlockIntervalInSecond: 10, CommitteeSize: 51, @@ -32,14 +32,16 @@ func DefaultParams() *Params { BondInterval: 360, // one hour UnbondInterval: 181440, // 21 days SortitionInterval: 17, - FeeFraction: 0.0001, - MinimumFee: 1000, - MaximumFee: 1000000, MinimumStake: 1000000000, MaximumStake: 1000000000000, + + // Deprecated: Replaced by fix fee + FeeFraction: 0.0, + MinimumFee: 0, + MaximumFee: 0, } } -func (p *Params) BlockInterval() time.Duration { +func (p *GenesisParams) BlockInterval() time.Duration { return time.Duration(p.BlockIntervalInSecond) * time.Second } diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go index 56e3284fc..0b8bedcff 100644 --- a/genesis/genesis_test.go +++ b/genesis/genesis_test.go @@ -10,7 +10,6 @@ import ( "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/testsuite" @@ -26,7 +25,7 @@ func TestMarshaling(t *testing.T) { val, _ := ts.GenerateTestValidator(0) gen1 := genesis.MakeGenesis(util.RoundNow(10), map[crypto.Address]*account.Account{prv: acc}, - []*validator.Validator{val}, param.DefaultParams()) + []*validator.Validator{val}, genesis.DefaultGenesisParams()) gen2 := new(genesis.Genesis) assert.Equal(t, 10, gen1.Params().BlockIntervalInSecond) @@ -95,7 +94,7 @@ func TestCheckGenesisAccountAndValidator(t *testing.T) { accs[pub.AccountAddress()] = acc vals = append(vals, val) } - gen := genesis.MakeGenesis(time.Now(), accs, vals, param.DefaultParams()) + gen := genesis.MakeGenesis(time.Now(), accs, vals, genesis.DefaultGenesisParams()) for addr, acc := range gen.Accounts() { assert.Equal(t, accs[addr], acc) diff --git a/genesis/testnet.json b/genesis/testnet.json index 3275ea629..2f5d73a51 100644 --- a/genesis/testnet.json +++ b/genesis/testnet.json @@ -51,4 +51,4 @@ "public_key": "tpublic1pjy7z27zm6795xhj8rln65cve88dtqjkg7gca6scxzwwfxpncnmkhg35n2rw3fa9e04cqcc8c9fyqvpm7y39wj0x2e5qrl0he60ms6v79vga3le2uvgn566p7x9exjnyhh3klycqddstj7339afnm73k09v8k52uy" } ] -} +} \ No newline at end of file diff --git a/node/node_test.go b/node/node_test.go index 2cfc4f107..04c4520ab 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -10,7 +10,6 @@ import ( "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/types/account" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/logger" @@ -30,7 +29,7 @@ func TestRunningNode(t *testing.T) { val := validator.NewValidator(pub, 0) gen := genesis.MakeGenesis(time.Now(), map[crypto.Address]*account.Account{crypto.TreasuryAddress: acc}, - []*validator.Validator{val}, param.DefaultParams()) + []*validator.Validator{val}, genesis.DefaultGenesisParams()) conf := config.DefaultConfigMainnet() conf.GRPC.Enable = true conf.GRPC.Listen = "0.0.0.0:0" diff --git a/sandbox/interface.go b/sandbox/interface.go index 8e4da284c..a25355335 100644 --- a/sandbox/interface.go +++ b/sandbox/interface.go @@ -5,9 +5,9 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/sortition" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/validator" ) diff --git a/sandbox/mock.go b/sandbox/mock.go index 9b82e2112..dde44cdc6 100644 --- a/sandbox/mock.go +++ b/sandbox/mock.go @@ -4,11 +4,12 @@ import ( "github.com/pactus-project/pactus/committee" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/sortition" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util/testsuite" @@ -34,7 +35,7 @@ func MockingSandbox(ts *testsuite.TestSuite) *MockSandbox { sb := &MockSandbox{ ts: ts, - TestParams: param.DefaultParams(), + TestParams: param.FromGenesis(genesis.DefaultGenesisParams()), TestStore: store.MockingStore(ts), TestCommittee: cmt, TestJoinedValidators: make(map[crypto.Address]bool), diff --git a/sandbox/sandbox.go b/sandbox/sandbox.go index 29e92987a..87331471e 100644 --- a/sandbox/sandbox.go +++ b/sandbox/sandbox.go @@ -7,10 +7,10 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/sortition" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util/logger" diff --git a/sandbox/sandbox_test.go b/sandbox/sandbox_test.go index 414a5c4fe..42f0d84c0 100644 --- a/sandbox/sandbox_test.go +++ b/sandbox/sandbox_test.go @@ -5,11 +5,12 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/sortition" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util/testsuite" "github.com/stretchr/testify/assert" @@ -28,7 +29,7 @@ func setup(t *testing.T) *testData { ts := testsuite.NewTestSuite(t) mockStore := store.MockingStore(ts) - params := param.DefaultParams() + params := genesis.DefaultGenesisParams() params.TransactionToLiveInterval = 64 cmt, valKeys := ts.GenerateTestCommittee(21) @@ -54,9 +55,9 @@ func setup(t *testing.T) *testData { mockStore.SaveBlock(blk, cert) } sandbox := NewSandbox(mockStore.LastHeight, - mockStore, params, cmt, totalPower).(*sandbox) + mockStore, param.FromGenesis(params), cmt, totalPower).(*sandbox) assert.Equal(t, lastHeight, sandbox.CurrentHeight()) - assert.Equal(t, params, sandbox.Params()) + assert.Equal(t, param.FromGenesis(params), sandbox.Params()) return &testData{ TestSuite: ts, diff --git a/state/facade.go b/state/facade.go index a7bb09399..6b3bfb633 100644 --- a/state/facade.go +++ b/state/facade.go @@ -7,12 +7,12 @@ import ( "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/genesis" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/certificate" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/tx/payload" "github.com/pactus-project/pactus/types/validator" diff --git a/state/mock.go b/state/mock.go index 4a2849edf..3d9d51d5e 100644 --- a/state/mock.go +++ b/state/mock.go @@ -10,13 +10,13 @@ import ( "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/genesis" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/txpool" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/certificate" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/tx/payload" "github.com/pactus-project/pactus/types/validator" @@ -51,7 +51,7 @@ func MockingState(ts *testsuite.TestSuite) *MockState { TestPool: txpool.MockingTxPool(), TestCommittee: cmt, TestValKeys: valKeys, - TestParams: genDoc.Params(), + TestParams: param.FromGenesis(genDoc.Params()), } } diff --git a/state/param/param.go b/state/param/param.go new file mode 100644 index 000000000..1ac2694b8 --- /dev/null +++ b/state/param/param.go @@ -0,0 +1,45 @@ +package param + +import ( + "time" + + "github.com/pactus-project/pactus/genesis" + "github.com/pactus-project/pactus/types/amount" +) + +type Params struct { + BlockVersion uint8 + BlockIntervalInSecond int + MaxTransactionsPerBlock int + CommitteeSize int + BlockReward amount.Amount + TransactionToLiveInterval uint32 + BondInterval uint32 + UnbondInterval uint32 + SortitionInterval uint32 + MinimumStake amount.Amount + MaximumStake amount.Amount +} + +func FromGenesis(genDoc *genesis.GenesisParams) *Params { + return &Params{ + // genesis parameters + BlockVersion: genDoc.BlockVersion, + BlockIntervalInSecond: genDoc.BlockIntervalInSecond, + CommitteeSize: genDoc.CommitteeSize, + BlockReward: genDoc.BlockReward, + TransactionToLiveInterval: genDoc.TransactionToLiveInterval, + BondInterval: genDoc.BondInterval, + UnbondInterval: genDoc.UnbondInterval, + SortitionInterval: genDoc.SortitionInterval, + MaximumStake: genDoc.MaximumStake, + MinimumStake: genDoc.MinimumStake, + + // chain parameters + MaxTransactionsPerBlock: 1000, + } +} + +func (p *Params) BlockInterval() time.Duration { + return time.Duration(p.BlockIntervalInSecond) * time.Second +} diff --git a/state/state.go b/state/state.go index e9ab9ad46..97f590c5c 100644 --- a/state/state.go +++ b/state/state.go @@ -15,6 +15,7 @@ import ( "github.com/pactus-project/pactus/sandbox" "github.com/pactus-project/pactus/sortition" "github.com/pactus-project/pactus/state/lastinfo" + "github.com/pactus-project/pactus/state/param" "github.com/pactus-project/pactus/state/score" "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/txpool" @@ -22,7 +23,6 @@ import ( "github.com/pactus-project/pactus/types/amount" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/certificate" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/tx/payload" "github.com/pactus-project/pactus/types/validator" @@ -35,8 +35,6 @@ import ( "github.com/pactus-project/pactus/www/nanomsg/event" ) -var maxTransactionsPerBlock = 1000 - type state struct { lk sync.RWMutex @@ -65,7 +63,7 @@ func LoadOrNewState( valKeys: valKeys, genDoc: genDoc, txPool: txPool, - params: genDoc.Params(), + params: param.FromGenesis(genDoc.Params()), store: str, lastInfo: lastinfo.NewLastInfo(), accountMerkle: persistentmerkle.New(), @@ -323,7 +321,7 @@ func (st *state) ProposeBlock(valKey *bls.ValidatorKey, rewardAddr crypto.Addres // Re-check all transactions strictly and remove invalid ones txs := st.txPool.PrepareBlockTransactions() - txs = util.Trim(txs, maxTransactionsPerBlock-1) + txs = util.Trim(txs, st.params.MaxTransactionsPerBlock-1) for i := 0; i < txs.Len(); i++ { // Only one subsidy transaction per blk if txs[i].IsSubsidyTx() { diff --git a/state/state_test.go b/state/state_test.go index 2ea3fbcc2..2905fa560 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -13,7 +13,6 @@ import ( "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/certificate" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/tx/payload" "github.com/pactus-project/pactus/types/validator" @@ -55,9 +54,9 @@ func setup(t *testing.T) *testData { genTime := util.RoundNow(10).Add(-8640 * time.Second) - params := param.DefaultParams() - params.CommitteeSize = 7 - params.BondInterval = 10 + genParams := genesis.DefaultGenesisParams() + genParams.CommitteeSize = 7 + genParams.BondInterval = 10 genAcc1 := account.NewAccount(0) genAcc1.AddToBalance(21 * 1e15) // 21,000,000.000,000,000 @@ -70,7 +69,7 @@ func setup(t *testing.T) *testData { genAccPubKey.AccountAddress(): genAcc2, } - gnDoc := genesis.MakeGenesis(genTime, genAccs, genVals, params) + gnDoc := genesis.MakeGenesis(genTime, genAccs, genVals, genParams) // First validator is in the committee valKeys := []*bls.ValidatorKey{genValKeys[0], ts.RandValKey()} @@ -585,10 +584,10 @@ func TestCalculateFee(t *testing.T) { func TestCheckMaximumTransactionPerBlock(t *testing.T) { td := setup(t) - maxTransactionsPerBlock = 10 + td.state.params.MaxTransactionsPerBlock = 10 lockTime := td.state.LastBlockHeight() senderAddr := td.genAccKey.PublicKeyNative().AccountAddress() - for i := 0; i < maxTransactionsPerBlock+2; i++ { + for i := 0; i < td.state.params.MaxTransactionsPerBlock+2; i++ { amt := td.RandAmount() fee := td.state.CalculateFee(amt, payload.TypeTransfer) trx := tx.NewTransferTx(lockTime, senderAddr, td.RandAccAddress(), amt, fee) @@ -598,7 +597,7 @@ func TestCheckMaximumTransactionPerBlock(t *testing.T) { blk, err := td.state.ProposeBlock(td.state.valKeys[0], td.RandAccAddress()) assert.NoError(t, err) - assert.Equal(t, maxTransactionsPerBlock, blk.Transactions().Len()) + assert.Equal(t, td.state.params.MaxTransactionsPerBlock, blk.Transactions().Len()) } func TestCommittedBlock(t *testing.T) { diff --git a/sync/firewall/firewall_test.go b/sync/firewall/firewall_test.go index 4c25a7e55..6e2a53697 100644 --- a/sync/firewall/firewall_test.go +++ b/sync/firewall/firewall_test.go @@ -354,7 +354,7 @@ func TestNetworkFlagsTestnet(t *testing.T) { func TestNetworkFlagsLocalnet(t *testing.T) { td := setup(t, nil) - td.state.TestParams.BlockVersion = 0x3f // changing genesis hash + td.state.Genesis().Params().BlockVersion = 0x3f // changing genesis hash bdl := bundle.NewBundle(message.NewQueryVoteMessage(td.RandHeight(), td.RandRound(), td.RandValAddress())) bdl.Flags = util.SetFlag(bdl.Flags, bundle.BundleFlagNetworkTestnet) diff --git a/tests/main_test.go b/tests/main_test.go index 5578a48d6..947383ecd 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -16,7 +16,6 @@ import ( "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/amount" - "github.com/pactus-project/pactus/types/param" "github.com/pactus-project/pactus/types/validator" "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/logger" @@ -119,13 +118,14 @@ func TestMain(m *testing.M) { vals[1] = validator.NewValidator(tValKeys[tNodeIdx2][0].PublicKey(), 1) vals[2] = validator.NewValidator(tValKeys[tNodeIdx3][0].PublicKey(), 2) vals[3] = validator.NewValidator(tValKeys[tNodeIdx4][0].PublicKey(), 3) - params := param.DefaultParams() - params.MinimumStake = 1000 - params.BlockIntervalInSecond = 2 - params.BondInterval = 8 - params.CommitteeSize = tCommitteeSize - params.TransactionToLiveInterval = 8 - tGenDoc = genesis.MakeGenesis(time.Now(), accs, vals, params) + + genParams := genesis.DefaultGenesisParams() + genParams.MinimumStake = 1000 + genParams.BlockIntervalInSecond = 2 + genParams.BondInterval = 8 + genParams.CommitteeSize = tCommitteeSize + genParams.TransactionToLiveInterval = 8 + tGenDoc = genesis.MakeGenesis(time.Now(), accs, vals, genParams) for i := 0; i < tTotalNodes; i++ { tNodes[i], _ = node.NewNode( From 58b0cf27818b42205a63417de73b947bac358b7a Mon Sep 17 00:00:00 2001 From: K Date: Tue, 13 Aug 2024 18:01:22 +0330 Subject: [PATCH 08/25] fix(shell): stop showing usage on error (#1467) --- cmd/shell/main.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmd/shell/main.go b/cmd/shell/main.go index a3a46a896..e5461ea94 100644 --- a/cmd/shell/main.go +++ b/cmd/shell/main.go @@ -31,9 +31,10 @@ func main() { ) rootCmd := &cobra.Command{ - Use: "shell", - Short: "Pactus Shell", - Long: `pactus-shell is a command line tool for interacting with the Pactus blockchain using gRPC`, + Use: "shell", + Short: "Pactus Shell", + SilenceUsage: true, + Long: `pactus-shell is a command line tool for interacting with the Pactus blockchain using gRPC`, } sh := shell.New(rootCmd, nil, @@ -91,7 +92,7 @@ func main() { err := rootCmd.Execute() if err != nil { - cmd.PrintErrorMsgf("%s", err) + cmd.PrintErrorMsgf(err.Error()) } } From 80218244a09f92d2461b27c82c1e34b11764c323 Mon Sep 17 00:00:00 2001 From: K Date: Tue, 13 Aug 2024 20:04:37 +0330 Subject: [PATCH 09/25] feat(daemon): warn at pruning a prune node attempt (#1471) --- cmd/daemon/prune.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/daemon/prune.go b/cmd/daemon/prune.go index a58c2ab89..82b917061 100644 --- a/cmd/daemon/prune.go +++ b/cmd/daemon/prune.go @@ -95,6 +95,11 @@ func buildPruneCmd(parentCmd *cobra.Command) { cmd.PrintLine() cmd.PrintInfoMsgf("❌ The operation canceled.") cmd.PrintLine() + } else if prunedCount == 0 { + cmd.PrintLine() + cmd.PrintInfoMsgf("⚠️ Your node is not passed the retention_days set in config or it's already a pruned node.") + cmd.PrintLine() + cmd.PrintInfoMsgf("Make sure you try to prune a node after retention_days specified in config.toml") } else { cmd.PrintLine() cmd.PrintInfoMsgf("✅ Your node successfully pruned and changed to prune mode.") From 83261e18fbfd9105c5657e212602f086a6d9aae1 Mon Sep 17 00:00:00 2001 From: K Date: Wed, 14 Aug 2024 09:54:50 +0330 Subject: [PATCH 10/25] feat(gtk): adding IsPrune to node widget (#1470) Co-authored-by: Javad Rajabzadeh --- cmd/gtk/assets/ui/widget_node.ui | 35 ++++++++++++++++++++++++++++---- cmd/gtk/widget_node.go | 2 ++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/cmd/gtk/assets/ui/widget_node.ui b/cmd/gtk/assets/ui/widget_node.ui index 7441c68e2..07a97c25f 100644 --- a/cmd/gtk/assets/ui/widget_node.ui +++ b/cmd/gtk/assets/ui/widget_node.ui @@ -1,5 +1,5 @@ - + @@ -48,7 +48,7 @@ 0.019999999552965164 in - + 400 True @@ -191,7 +191,7 @@ 0 - 10 + 11 @@ -204,7 +204,7 @@ 1 - 10 + 11 @@ -386,6 +386,33 @@ 6 + + + True + False + start + True + True + ✂️ Is Prune: + + + 0 + 10 + + + + + True + False + start + True + True + + + 1 + 10 + + diff --git a/cmd/gtk/widget_node.go b/cmd/gtk/widget_node.go index 66b1599ea..f518d5978 100644 --- a/cmd/gtk/widget_node.go +++ b/cmd/gtk/widget_node.go @@ -48,6 +48,7 @@ func buildWidgetNode(model *nodeModel) (*widgetNode, error) { labelNetwork := getLabelObj(builder, "id_label_network") labelNetworkID := getLabelObj(builder, "id_label_network_id") labelMoniker := getLabelObj(builder, "id_label_moniker") + labelIsPrune := getLabelObj(builder, "id_label_is_prune") cwd, err := os.Getwd() if err != nil { @@ -57,6 +58,7 @@ func buildWidgetNode(model *nodeModel) (*widgetNode, error) { labelNetwork.SetText(model.node.State().Genesis().ChainType().String()) labelNetworkID.SetText(model.node.Network().SelfID().String()) labelMoniker.SetText(model.node.Sync().Moniker()) + labelIsPrune.SetText(strconv.FormatBool(model.node.State().IsPruned())) w := &widgetNode{ Box: box, From e7734444d7fcb07d46275e65149da2c3f34e217c Mon Sep 17 00:00:00 2001 From: K Date: Wed, 14 Aug 2024 09:55:47 +0330 Subject: [PATCH 11/25] docs(gtk): adding GTK GUI development guide (#1472) --- CONTRIBUTING.md | 7 ++++- docs/gtk-gui-development.md | 52 +++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 docs/gtk-gui-development.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9308d8500..b6dc68e9b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,6 +19,7 @@ Please follow these guidelines when contributing to the project: You can use these commands in the Makefile: - `make build` compiles the code into executable binaries. +- `make build_gui` compiles the gtk GUI code into executable binary. - `make devtools` installs required development tools. - `make fmt` formats the code according to the Go standards. - `make check` runs checks on the code, including formatting and linting. @@ -27,6 +28,10 @@ You can use these commands in the Makefile: - `make proto` generates [protobuf](https://protobuf.dev/) files. Run this target if you have made any changes to the proto buffer files. +### GUI Development + +Development of the Pactus Core GUI have some requirements on your machine which you can find a [quick guide about it here](./docs/gtk-gui-development.md). + ### Error and Log Messages Error and log messages should not start with a capital letter (unless it's a proper noun or acronym) and @@ -115,4 +120,4 @@ Please read it before contributing to the project. --- -Thank you for your contributions to Pactus blockchain! +Thank you for your contributions to the Pactus blockchain! diff --git a/docs/gtk-gui-development.md b/docs/gtk-gui-development.md new file mode 100644 index 000000000..edd42b67f --- /dev/null +++ b/docs/gtk-gui-development.md @@ -0,0 +1,52 @@ +# Pactus GUI + +This document is quick guide for developing and updating [the Pactus Core GUI](../cmd/gtk/). + +## Requirements + +The Pactus Core GUI utilizes gtk for desktop GUI. To develop, build and test it you must have these packages installed: + +### Linux + +1. `libgtk-3-dev` +2. `libcairo2-dev` +3. `libglib2.0-dev` + +Install using apt: + +```bash +apt install libgtk-3-dev libcairo2-dev libglib2.0-dev +``` + +### Mac OS + +1. `gtk+3` + +Install using brew: + +```bash +brew install gtk+3 +``` + +### Windows + +1. `glib2-devel` +2. `mingw-w64-x86_64-go` +3. `mingw-w64-x86_64-gtk3` +4. `mingw-w64-x86_64-glib2` +5. `mingw-w64-x86_64-gcc` +6. `mingw-w64-x86_64-pkg-config` + + +With these packages installed you can build GUI using `make build_gui` command. You can run the GUI like: `./pactus-gui`, `./pactus-gui.exe`. + + +The [Assets](../cmd/gtk/assets/) file includes required images, icons, ui files and custom CSS files. All [`.ui`](../cmd/gtk/assets/ui/) files are used to defined the user interface of GUI, for a proper edit and change on them make sure you have [Glade](https://gitlab.gnome.org/GNOME/glade) installed on your machine. + +## Running linter + +When you make changes on GUI files and try to run linter using `make check`, it won't include [gtk](../cmd/gtk/) in it's checks. So make sure you add gtk build flag like this: + +```bash +BUILD_TAG=gtk make check +``` From 57b9bec72a0090a4dc52c2784462465b1423b31f Mon Sep 17 00:00:00 2001 From: b00f Date: Fri, 16 Aug 2024 13:15:24 +0800 Subject: [PATCH 12/25] fix(grpc): change enum type to numeric for documentation (#1474) --- Makefile | 2 +- www/grpc/buf/grpc-md.tmpl | 8 +- www/grpc/buf/json-rpc-md.tmpl | 8 +- www/grpc/gen/docs/grpc.md | 85 ++++++++------- www/grpc/gen/docs/json-rpc.md | 103 +++++++++--------- www/grpc/gen/go/wallet.pb.go | 8 +- .../java/pactus/wallet/WalletOuterClass.java | 26 +++++ www/grpc/gen/rust/pactus.rs | 4 + www/grpc/proto/wallet.proto | 4 + www/grpc/swagger-ui/pactus.swagger.json | 4 +- 10 files changed, 146 insertions(+), 106 deletions(-) diff --git a/Makefile b/Makefile index e0d85b568..42dbd216b 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ devtools: go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4 go install github.com/NathanBaulch/protoc-gen-cobra@v1.2 - go install github.com/pactus-project/protoc-gen-doc/cmd/protoc-gen-doc@v0.0.0-20240619124021-76fc28241eb6 + go install github.com/pactus-project/protoc-gen-doc/cmd/protoc-gen-doc@v0.0.0-20240815105130-84e89d0170e4 go install github.com/bufbuild/buf/cmd/buf@v1.34 go install mvdan.cc/gofumpt@latest go install github.com/rakyll/statik@v0.1.7 diff --git a/www/grpc/buf/grpc-md.tmpl b/www/grpc/buf/grpc-md.tmpl index ee82bf3ce..5d68bf4ca 100644 --- a/www/grpc/buf/grpc-md.tmpl +++ b/www/grpc/buf/grpc-md.tmpl @@ -64,7 +64,7 @@ Each PAC is equivalent to 1,000,000,000 or 109 NanoPACs. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} @@ -99,7 +99,7 @@ Message has no fields. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} @@ -119,7 +119,7 @@ Message has no fields. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} @@ -139,7 +139,7 @@ Message has no fields. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} diff --git a/www/grpc/buf/json-rpc-md.tmpl b/www/grpc/buf/json-rpc-md.tmpl index bf2f37433..61e84f968 100644 --- a/www/grpc/buf/json-rpc-md.tmpl +++ b/www/grpc/buf/json-rpc-md.tmpl @@ -115,7 +115,7 @@ curl --location 'http://localhost:8545/' \ {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} @@ -150,7 +150,7 @@ Parameters has no fields. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} @@ -170,7 +170,7 @@ Parameters has no fields. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} @@ -190,7 +190,7 @@ Parameters has no fields. {{with getEnum .LongType }}{{- print "" -}}
      Available values:
        {{range .Values}}{{- print "" -}} -
      • {{ .Name}} = {{ .Description }}
      • +
      • {{.Name}} = {{.Number}} ({{ .Description }})
      • {{end}}{{- print "" -}}
      {{end}}{{- print "" -}} diff --git a/www/grpc/gen/docs/grpc.md b/www/grpc/gen/docs/grpc.md index 4a5202701..583f0ef30 100644 --- a/www/grpc/gen/docs/grpc.md +++ b/www/grpc/gen/docs/grpc.md @@ -196,8 +196,8 @@ parameters.

      (Enum) The verbosity level for transaction details.
      Available values:
        -
      • TRANSACTION_DATA = Request transaction data only.
      • -
      • TRANSACTION_INFO = Request detailed transaction information.
      • +
      • TRANSACTION_DATA = 0 (Request transaction data only.)
      • +
      • TRANSACTION_INFO = 1 (Request detailed transaction information.)
      @@ -279,12 +279,12 @@ parameters.

      (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -456,12 +456,12 @@ and payload type.

      (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -842,9 +842,9 @@ parameters.

      (Enum) The verbosity level for block information.
      Available values:
        -
      • BLOCK_DATA = Request only block data.
      • -
      • BLOCK_INFO = Request block information and transaction IDs.
      • -
      • BLOCK_TRANSACTIONS = Request block information and detailed transaction data.
      • +
      • BLOCK_DATA = 0 (Request only block data.)
      • +
      • BLOCK_INFO = 1 (Request block information and transaction IDs.)
      • +
      • BLOCK_TRANSACTIONS = 2 (Request block information and detailed transaction data.)
      @@ -1025,12 +1025,12 @@ BLOCK_TRANSACTIONS. (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -1471,10 +1471,10 @@ committee. (Enum) The type of the vote.
      Available values:
        -
      • VOTE_UNKNOWN = Unknown vote type.
      • -
      • VOTE_PREPARE = Prepare vote type.
      • -
      • VOTE_PRECOMMIT = Precommit vote type.
      • -
      • VOTE_CHANGE_PROPOSER = Change proposer vote type.
      • +
      • VOTE_UNKNOWN = 0 (Unknown vote type.)
      • +
      • VOTE_PREPARE = 1 (Prepare vote type.)
      • +
      • VOTE_PRECOMMIT = 2 (Precommit vote type.)
      • +
      • VOTE_CHANGE_PROPOSER = 3 (Change proposer vote type.)
      @@ -1885,12 +1885,12 @@ address.

      (Enum) The type of transactions to retrieve from the transaction pool. 0 means all types.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -1958,12 +1958,12 @@ types. (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -2885,9 +2885,10 @@ public key.

      (Enum) The type of address to generate.
      Available values:
        -
      • ADDRESS_TYPE_TREASURY =
      • -
      • ADDRESS_TYPE_VALIDATOR =
      • -
      • ADDRESS_TYPE_BLS_ACCOUNT =
      • +
      • ADDRESS_TYPE_TREASURY = 0 (Treasury address type. +Should not be used to generate new addresses.)
      • +
      • ADDRESS_TYPE_VALIDATOR = 1 (Validator address type.)
      • +
      • ADDRESS_TYPE_BLS_ACCOUNT = 2 (Account address type with BLS signature scheme.)
      diff --git a/www/grpc/gen/docs/json-rpc.md b/www/grpc/gen/docs/json-rpc.md index af07bb94d..800aa3dc7 100644 --- a/www/grpc/gen/docs/json-rpc.md +++ b/www/grpc/gen/docs/json-rpc.md @@ -243,12 +243,12 @@ parameters.

      verbosity - string + numeric (Enum) The verbosity level for transaction details.
      Available values:
        -
      • TRANSACTION_DATA = Request transaction data only.
      • -
      • TRANSACTION_INFO = Request detailed transaction information.
      • +
      • TRANSACTION_DATA = 0 (Request transaction data only.)
      • +
      • TRANSACTION_INFO = 1 (Request detailed transaction information.)
      @@ -326,16 +326,16 @@ parameters.

      transaction.payload_type - string + numeric (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -503,16 +503,16 @@ and payload type.

      payload_type - string + numeric (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -889,13 +889,13 @@ parameters.

      verbosity - string + numeric (Enum) The verbosity level for block information.
      Available values:
        -
      • BLOCK_DATA = Request only block data.
      • -
      • BLOCK_INFO = Request block information and transaction IDs.
      • -
      • BLOCK_TRANSACTIONS = Request block information and detailed transaction data.
      • +
      • BLOCK_DATA = 0 (Request only block data.)
      • +
      • BLOCK_INFO = 1 (Request block information and transaction IDs.)
      • +
      • BLOCK_TRANSACTIONS = 2 (Request block information and detailed transaction data.)
      @@ -1072,16 +1072,16 @@ BLOCK_TRANSACTIONS. txs[].payload_type - string + numeric (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -1518,14 +1518,14 @@ committee. instances[].votes[].type - string + numeric (Enum) The type of the vote.
      Available values:
        -
      • VOTE_UNKNOWN = Unknown vote type.
      • -
      • VOTE_PREPARE = Prepare vote type.
      • -
      • VOTE_PRECOMMIT = Precommit vote type.
      • -
      • VOTE_CHANGE_PROPOSER = Change proposer vote type.
      • +
      • VOTE_UNKNOWN = 0 (Unknown vote type.)
      • +
      • VOTE_PREPARE = 1 (Prepare vote type.)
      • +
      • VOTE_PRECOMMIT = 2 (Precommit vote type.)
      • +
      • VOTE_CHANGE_PROPOSER = 3 (Change proposer vote type.)
      @@ -1931,17 +1931,17 @@ address.

      payload_type - string + numeric (Enum) The type of transactions to retrieve from the transaction pool. 0 means all types.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -2005,16 +2005,16 @@ types. txs[].payload_type - string + numeric (Enum) The type of transaction payload.
      Available values:
        -
      • UNKNOWN = Unknown payload type.
      • -
      • TRANSFER_PAYLOAD = Transfer payload type.
      • -
      • BOND_PAYLOAD = Bond payload type.
      • -
      • SORTITION_PAYLOAD = Sortition payload type.
      • -
      • UNBOND_PAYLOAD = Unbond payload type.
      • -
      • WITHDRAW_PAYLOAD = Withdraw payload type.
      • +
      • UNKNOWN = 0 (Unknown payload type.)
      • +
      • TRANSFER_PAYLOAD = 1 (Transfer payload type.)
      • +
      • BOND_PAYLOAD = 2 (Bond payload type.)
      • +
      • SORTITION_PAYLOAD = 3 (Sortition payload type.)
      • +
      • UNBOND_PAYLOAD = 4 (Unbond payload type.)
      • +
      • WITHDRAW_PAYLOAD = 5 (Withdraw payload type.)
      @@ -2932,13 +2932,14 @@ public key.

      address_type - string + numeric (Enum) The type of address to generate.
      Available values:
        -
      • ADDRESS_TYPE_TREASURY =
      • -
      • ADDRESS_TYPE_VALIDATOR =
      • -
      • ADDRESS_TYPE_BLS_ACCOUNT =
      • +
      • ADDRESS_TYPE_TREASURY = 0 (Treasury address type. +Should not be used to generate new addresses.)
      • +
      • ADDRESS_TYPE_VALIDATOR = 1 (Validator address type.)
      • +
      • ADDRESS_TYPE_BLS_ACCOUNT = 2 (Account address type with BLS signature scheme.)
      diff --git a/www/grpc/gen/go/wallet.pb.go b/www/grpc/gen/go/wallet.pb.go index 30c89c687..61a05eba7 100644 --- a/www/grpc/gen/go/wallet.pb.go +++ b/www/grpc/gen/go/wallet.pb.go @@ -26,8 +26,12 @@ const ( type AddressType int32 const ( - AddressType_ADDRESS_TYPE_TREASURY AddressType = 0 - AddressType_ADDRESS_TYPE_VALIDATOR AddressType = 1 + // Treasury address type. + // Should not be used to generate new addresses. + AddressType_ADDRESS_TYPE_TREASURY AddressType = 0 + // Validator address type. + AddressType_ADDRESS_TYPE_VALIDATOR AddressType = 1 + // Account address type with BLS signature scheme. AddressType_ADDRESS_TYPE_BLS_ACCOUNT AddressType = 2 ) diff --git a/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java b/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java index 57746fdb6..9cf8b97d7 100644 --- a/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java +++ b/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java @@ -24,14 +24,27 @@ public static void registerAllExtensions( public enum AddressType implements com.google.protobuf.ProtocolMessageEnum { /** + *
      +     * Treasury address type.
      +     * Should not be used to generate new addresses.
      +     * 
      + * * ADDRESS_TYPE_TREASURY = 0; */ ADDRESS_TYPE_TREASURY(0), /** + *
      +     * Validator address type.
      +     * 
      + * * ADDRESS_TYPE_VALIDATOR = 1; */ ADDRESS_TYPE_VALIDATOR(1), /** + *
      +     * Account address type with BLS signature scheme.
      +     * 
      + * * ADDRESS_TYPE_BLS_ACCOUNT = 2; */ ADDRESS_TYPE_BLS_ACCOUNT(2), @@ -39,14 +52,27 @@ public enum AddressType ; /** + *
      +     * Treasury address type.
      +     * Should not be used to generate new addresses.
      +     * 
      + * * ADDRESS_TYPE_TREASURY = 0; */ public static final int ADDRESS_TYPE_TREASURY_VALUE = 0; /** + *
      +     * Validator address type.
      +     * 
      + * * ADDRESS_TYPE_VALIDATOR = 1; */ public static final int ADDRESS_TYPE_VALIDATOR_VALUE = 1; /** + *
      +     * Account address type with BLS signature scheme.
      +     * 
      + * * ADDRESS_TYPE_BLS_ACCOUNT = 2; */ public static final int ADDRESS_TYPE_BLS_ACCOUNT_VALUE = 2; diff --git a/www/grpc/gen/rust/pactus.rs b/www/grpc/gen/rust/pactus.rs index 897e4a1b0..0ee61993b 100644 --- a/www/grpc/gen/rust/pactus.rs +++ b/www/grpc/gen/rust/pactus.rs @@ -1218,8 +1218,12 @@ pub struct SignMessageResponse { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum AddressType { + /// Treasury address type. + /// Should not be used to generate new addresses. Treasury = 0, + /// Validator address type. Validator = 1, + /// Account address type with BLS signature scheme. BlsAccount = 2, } impl AddressType { diff --git a/www/grpc/proto/wallet.proto b/www/grpc/proto/wallet.proto index b6dd88b1b..9deaa99bb 100644 --- a/www/grpc/proto/wallet.proto +++ b/www/grpc/proto/wallet.proto @@ -48,8 +48,12 @@ service Wallet { // Enum for the address type. enum AddressType { + // Treasury address type. + // Should not be used to generate new addresses. ADDRESS_TYPE_TREASURY = 0; + // Validator address type. ADDRESS_TYPE_VALIDATOR = 1; + // Account address type with BLS signature scheme. ADDRESS_TYPE_BLS_ACCOUNT = 2; } diff --git a/www/grpc/swagger-ui/pactus.swagger.json b/www/grpc/swagger-ui/pactus.swagger.json index c7a3d6e1e..fb438593b 100644 --- a/www/grpc/swagger-ui/pactus.swagger.json +++ b/www/grpc/swagger-ui/pactus.swagger.json @@ -971,7 +971,7 @@ }, { "name": "addressType", - "description": "The type of address to generate.", + "description": "The type of address to generate.\n\n - ADDRESS_TYPE_TREASURY: Treasury address type.\nShould not be used to generate new addresses.\n - ADDRESS_TYPE_VALIDATOR: Validator address type.\n - ADDRESS_TYPE_BLS_ACCOUNT: Account address type with BLS signature scheme.", "in": "query", "required": false, "type": "string", @@ -1328,7 +1328,7 @@ "ADDRESS_TYPE_BLS_ACCOUNT" ], "default": "ADDRESS_TYPE_TREASURY", - "description": "Enum for the address type." + "description": "Enum for the address type.\n\n - ADDRESS_TYPE_TREASURY: Treasury address type.\nShould not be used to generate new addresses.\n - ADDRESS_TYPE_VALIDATOR: Validator address type.\n - ADDRESS_TYPE_BLS_ACCOUNT: Account address type with BLS signature scheme." }, "pactusBlockHeaderInfo": { "type": "object", From b7e0039b8bf8de7d7f6a246e4166603f4514b991 Mon Sep 17 00:00:00 2001 From: K Date: Tue, 20 Aug 2024 10:39:57 +0330 Subject: [PATCH 13/25] fix(grpc): adding pyi files for python generated files (#1479) --- scripts/snapshot.py | 63 ++++-- www/grpc/buf/buf.gen.yaml | 2 + www/grpc/gen/python/blockchain_pb2.pyi | 276 ++++++++++++++++++++++++ www/grpc/gen/python/network_pb2.pyi | 142 ++++++++++++ www/grpc/gen/python/transaction_pb2.pyi | 219 +++++++++++++++++++ www/grpc/gen/python/utils_pb2.pyi | 35 +++ www/grpc/gen/python/wallet_pb2.pyi | 191 ++++++++++++++++ 7 files changed, 906 insertions(+), 22 deletions(-) create mode 100644 www/grpc/gen/python/blockchain_pb2.pyi create mode 100644 www/grpc/gen/python/network_pb2.pyi create mode 100644 www/grpc/gen/python/transaction_pb2.pyi create mode 100644 www/grpc/gen/python/utils_pb2.pyi create mode 100644 www/grpc/gen/python/wallet_pb2.pyi diff --git a/scripts/snapshot.py b/scripts/snapshot.py index a00c55d94..09151cb70 100644 --- a/scripts/snapshot.py +++ b/scripts/snapshot.py @@ -75,7 +75,7 @@ def update_metadata_file(snapshot_path, snapshot_metadata): "name": snapshot_metadata["name"], "created_at": snapshot_metadata["created_at"], "compress": snapshot_metadata["compress"], - "data": snapshot_metadata["data"] + "data": snapshot_metadata["data"], } metadata.append(formatted_metadata) @@ -107,11 +107,13 @@ def create_snapshot_json(data_dir, snapshot_subdir): for filename in filenames: file_path = os.path.join(root, filename) rel_path = os.path.relpath(file_path, data_dir) - snapshot_rel_path = os.path.join(snapshot_subdir, rel_path).replace('\\', '/') + snapshot_rel_path = os.path.join(snapshot_subdir, rel_path).replace( + "\\", "/" + ) file_info = { "name": filename, "path": snapshot_rel_path, - "sha": Metadata.sha256(file_path) + "sha": Metadata.sha256(file_path), } files.append(file_info) @@ -207,30 +209,34 @@ def create_snapshot(self): logging.info(f"Creating snapshot directory '{snapshot_dir}'") os.makedirs(snapshot_dir, exist_ok=True) - data_dir = os.path.join(snapshot_dir, 'data') - if self.args.compress == 'none': + data_dir = os.path.join(snapshot_dir, "data") + if self.args.compress == "none": logging.info(f"Copying data from '{self.args.data_path}' to '{data_dir}'") shutil.copytree(self.args.data_path, data_dir) snapshot_metadata = Metadata.create_snapshot_json(data_dir, timestamp_str) - elif self.args.compress == 'zip': - zip_file = os.path.join(snapshot_dir, 'data.zip') + elif self.args.compress == "zip": + zip_file = os.path.join(snapshot_dir, "data.zip") rel = os.path.relpath(zip_file, snapshot_dir) meta_path = os.path.join(timestamp_str, rel) logging.info(f"Creating ZIP archive '{zip_file}'") - with zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED) as zipf: + with zipfile.ZipFile(zip_file, "w", zipfile.ZIP_DEFLATED) as zipf: for root, _, files in os.walk(self.args.data_path): for file in files: full_path = os.path.join(root, file) rel_path = os.path.relpath(full_path, self.args.data_path) - zipf.write(full_path, os.path.join('data', rel_path)) - snapshot_metadata = Metadata.create_compressed_snapshot_json(zip_file, meta_path) - elif self.args.compress == 'tar': - tar_file = os.path.join(snapshot_dir, 'data.tar.gz') + zipf.write(full_path, os.path.join("data", rel_path)) + snapshot_metadata = Metadata.create_compressed_snapshot_json( + zip_file, meta_path + ) + elif self.args.compress == "tar": + tar_file = os.path.join(snapshot_dir, "data.tar.gz") rel = os.path.relpath(tar_file, snapshot_dir) meta_path = os.path.join(timestamp_str, rel) logging.info(f"Creating TAR.GZ archive '{tar_file}'") - subprocess.run(['tar', '-czvf', tar_file, '-C', self.args.data_path, '.']) - snapshot_metadata = Metadata.create_compressed_snapshot_json(tar_file, meta_path) + subprocess.run(["tar", "-czvf", tar_file, "-C", self.args.data_path, "."]) + snapshot_metadata = Metadata.create_compressed_snapshot_json( + tar_file, meta_path + ) snapshot_metadata["name"] = timestamp_str snapshot_metadata["created_at"] = get_current_time_iso() @@ -313,14 +319,27 @@ def run(self): def parse_args(): user_home = os.path.expanduser("~") - default_data_path = os.path.join(user_home, 'pactus') - - parser = argparse.ArgumentParser(description='Pactus Blockchain Snapshot Tool') - parser.add_argument('--service_path', required=True, help='Path to pactus systemctl service') - parser.add_argument('--data_path', default=default_data_path, help='Path to data directory') - parser.add_argument('--compress', choices=['none', 'zip', 'tar'], default='none', help='Compression type') - parser.add_argument('--retention', type=int, default=3, help='Number of snapshots to retain') - parser.add_argument('--snapshot_path', default=os.getcwd(), help='Path to store snapshots') + default_data_path = os.path.join(user_home, "pactus") + + parser = argparse.ArgumentParser(description="Pactus Blockchain Snapshot Tool") + parser.add_argument( + "--service_path", required=True, help="Path to pactus systemctl service" + ) + parser.add_argument( + "--data_path", default=default_data_path, help="Path to data directory" + ) + parser.add_argument( + "--compress", + choices=["none", "zip", "tar"], + default="none", + help="Compression type", + ) + parser.add_argument( + "--retention", type=int, default=3, help="Number of snapshots to retain" + ) + parser.add_argument( + "--snapshot_path", default=os.getcwd(), help="Path to store snapshots" + ) return parser.parse_args() diff --git a/www/grpc/buf/buf.gen.yaml b/www/grpc/buf/buf.gen.yaml index 35c30b9aa..ccc95ac1a 100644 --- a/www/grpc/buf/buf.gen.yaml +++ b/www/grpc/buf/buf.gen.yaml @@ -48,6 +48,8 @@ plugins: out: ../gen/python - plugin: buf.build/grpc/python:v1.50.0 out: ../gen/python + - plugin: buf.build/protocolbuffers/pyi:v27.2 + out: ../gen/python # Rust code gen: # https://github.com/neoeinstein/protoc-gen-prost?tab=readme-ov-file#example-bufgenyaml - plugin: buf.build/community/neoeinstein-prost:v0.2.3 diff --git a/www/grpc/gen/python/blockchain_pb2.pyi b/www/grpc/gen/python/blockchain_pb2.pyi new file mode 100644 index 000000000..85a5b127d --- /dev/null +++ b/www/grpc/gen/python/blockchain_pb2.pyi @@ -0,0 +1,276 @@ +import transaction_pb2 as _transaction_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class BlockVerbosity(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + BLOCK_DATA: _ClassVar[BlockVerbosity] + BLOCK_INFO: _ClassVar[BlockVerbosity] + BLOCK_TRANSACTIONS: _ClassVar[BlockVerbosity] + +class VoteType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + VOTE_UNKNOWN: _ClassVar[VoteType] + VOTE_PREPARE: _ClassVar[VoteType] + VOTE_PRECOMMIT: _ClassVar[VoteType] + VOTE_CHANGE_PROPOSER: _ClassVar[VoteType] +BLOCK_DATA: BlockVerbosity +BLOCK_INFO: BlockVerbosity +BLOCK_TRANSACTIONS: BlockVerbosity +VOTE_UNKNOWN: VoteType +VOTE_PREPARE: VoteType +VOTE_PRECOMMIT: VoteType +VOTE_CHANGE_PROPOSER: VoteType + +class GetAccountRequest(_message.Message): + __slots__ = ("address",) + ADDRESS_FIELD_NUMBER: _ClassVar[int] + address: str + def __init__(self, address: _Optional[str] = ...) -> None: ... + +class GetAccountResponse(_message.Message): + __slots__ = ("account",) + ACCOUNT_FIELD_NUMBER: _ClassVar[int] + account: AccountInfo + def __init__(self, account: _Optional[_Union[AccountInfo, _Mapping]] = ...) -> None: ... + +class GetValidatorAddressesRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class GetValidatorAddressesResponse(_message.Message): + __slots__ = ("addresses",) + ADDRESSES_FIELD_NUMBER: _ClassVar[int] + addresses: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, addresses: _Optional[_Iterable[str]] = ...) -> None: ... + +class GetValidatorRequest(_message.Message): + __slots__ = ("address",) + ADDRESS_FIELD_NUMBER: _ClassVar[int] + address: str + def __init__(self, address: _Optional[str] = ...) -> None: ... + +class GetValidatorByNumberRequest(_message.Message): + __slots__ = ("number",) + NUMBER_FIELD_NUMBER: _ClassVar[int] + number: int + def __init__(self, number: _Optional[int] = ...) -> None: ... + +class GetValidatorResponse(_message.Message): + __slots__ = ("validator",) + VALIDATOR_FIELD_NUMBER: _ClassVar[int] + validator: ValidatorInfo + def __init__(self, validator: _Optional[_Union[ValidatorInfo, _Mapping]] = ...) -> None: ... + +class GetPublicKeyRequest(_message.Message): + __slots__ = ("address",) + ADDRESS_FIELD_NUMBER: _ClassVar[int] + address: str + def __init__(self, address: _Optional[str] = ...) -> None: ... + +class GetPublicKeyResponse(_message.Message): + __slots__ = ("public_key",) + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + public_key: str + def __init__(self, public_key: _Optional[str] = ...) -> None: ... + +class GetBlockRequest(_message.Message): + __slots__ = ("height", "verbosity") + HEIGHT_FIELD_NUMBER: _ClassVar[int] + VERBOSITY_FIELD_NUMBER: _ClassVar[int] + height: int + verbosity: BlockVerbosity + def __init__(self, height: _Optional[int] = ..., verbosity: _Optional[_Union[BlockVerbosity, str]] = ...) -> None: ... + +class GetBlockResponse(_message.Message): + __slots__ = ("height", "hash", "data", "block_time", "header", "prev_cert", "txs") + HEIGHT_FIELD_NUMBER: _ClassVar[int] + HASH_FIELD_NUMBER: _ClassVar[int] + DATA_FIELD_NUMBER: _ClassVar[int] + BLOCK_TIME_FIELD_NUMBER: _ClassVar[int] + HEADER_FIELD_NUMBER: _ClassVar[int] + PREV_CERT_FIELD_NUMBER: _ClassVar[int] + TXS_FIELD_NUMBER: _ClassVar[int] + height: int + hash: str + data: str + block_time: int + header: BlockHeaderInfo + prev_cert: CertificateInfo + txs: _containers.RepeatedCompositeFieldContainer[_transaction_pb2.TransactionInfo] + def __init__(self, height: _Optional[int] = ..., hash: _Optional[str] = ..., data: _Optional[str] = ..., block_time: _Optional[int] = ..., header: _Optional[_Union[BlockHeaderInfo, _Mapping]] = ..., prev_cert: _Optional[_Union[CertificateInfo, _Mapping]] = ..., txs: _Optional[_Iterable[_Union[_transaction_pb2.TransactionInfo, _Mapping]]] = ...) -> None: ... + +class GetBlockHashRequest(_message.Message): + __slots__ = ("height",) + HEIGHT_FIELD_NUMBER: _ClassVar[int] + height: int + def __init__(self, height: _Optional[int] = ...) -> None: ... + +class GetBlockHashResponse(_message.Message): + __slots__ = ("hash",) + HASH_FIELD_NUMBER: _ClassVar[int] + hash: str + def __init__(self, hash: _Optional[str] = ...) -> None: ... + +class GetBlockHeightRequest(_message.Message): + __slots__ = ("hash",) + HASH_FIELD_NUMBER: _ClassVar[int] + hash: str + def __init__(self, hash: _Optional[str] = ...) -> None: ... + +class GetBlockHeightResponse(_message.Message): + __slots__ = ("height",) + HEIGHT_FIELD_NUMBER: _ClassVar[int] + height: int + def __init__(self, height: _Optional[int] = ...) -> None: ... + +class GetBlockchainInfoRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class GetBlockchainInfoResponse(_message.Message): + __slots__ = ("last_block_height", "last_block_hash", "total_accounts", "total_validators", "total_power", "committee_power", "committee_validators", "is_pruned", "pruning_height", "last_block_time") + LAST_BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] + LAST_BLOCK_HASH_FIELD_NUMBER: _ClassVar[int] + TOTAL_ACCOUNTS_FIELD_NUMBER: _ClassVar[int] + TOTAL_VALIDATORS_FIELD_NUMBER: _ClassVar[int] + TOTAL_POWER_FIELD_NUMBER: _ClassVar[int] + COMMITTEE_POWER_FIELD_NUMBER: _ClassVar[int] + COMMITTEE_VALIDATORS_FIELD_NUMBER: _ClassVar[int] + IS_PRUNED_FIELD_NUMBER: _ClassVar[int] + PRUNING_HEIGHT_FIELD_NUMBER: _ClassVar[int] + LAST_BLOCK_TIME_FIELD_NUMBER: _ClassVar[int] + last_block_height: int + last_block_hash: str + total_accounts: int + total_validators: int + total_power: int + committee_power: int + committee_validators: _containers.RepeatedCompositeFieldContainer[ValidatorInfo] + is_pruned: bool + pruning_height: int + last_block_time: int + def __init__(self, last_block_height: _Optional[int] = ..., last_block_hash: _Optional[str] = ..., total_accounts: _Optional[int] = ..., total_validators: _Optional[int] = ..., total_power: _Optional[int] = ..., committee_power: _Optional[int] = ..., committee_validators: _Optional[_Iterable[_Union[ValidatorInfo, _Mapping]]] = ..., is_pruned: bool = ..., pruning_height: _Optional[int] = ..., last_block_time: _Optional[int] = ...) -> None: ... + +class GetConsensusInfoRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class GetConsensusInfoResponse(_message.Message): + __slots__ = ("instances",) + INSTANCES_FIELD_NUMBER: _ClassVar[int] + instances: _containers.RepeatedCompositeFieldContainer[ConsensusInfo] + def __init__(self, instances: _Optional[_Iterable[_Union[ConsensusInfo, _Mapping]]] = ...) -> None: ... + +class GetTxPoolContentRequest(_message.Message): + __slots__ = ("payload_type",) + PAYLOAD_TYPE_FIELD_NUMBER: _ClassVar[int] + payload_type: _transaction_pb2.PayloadType + def __init__(self, payload_type: _Optional[_Union[_transaction_pb2.PayloadType, str]] = ...) -> None: ... + +class GetTxPoolContentResponse(_message.Message): + __slots__ = ("txs",) + TXS_FIELD_NUMBER: _ClassVar[int] + txs: _containers.RepeatedCompositeFieldContainer[_transaction_pb2.TransactionInfo] + def __init__(self, txs: _Optional[_Iterable[_Union[_transaction_pb2.TransactionInfo, _Mapping]]] = ...) -> None: ... + +class ValidatorInfo(_message.Message): + __slots__ = ("hash", "data", "public_key", "number", "stake", "last_bonding_height", "last_sortition_height", "unbonding_height", "address", "availability_score") + HASH_FIELD_NUMBER: _ClassVar[int] + DATA_FIELD_NUMBER: _ClassVar[int] + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + NUMBER_FIELD_NUMBER: _ClassVar[int] + STAKE_FIELD_NUMBER: _ClassVar[int] + LAST_BONDING_HEIGHT_FIELD_NUMBER: _ClassVar[int] + LAST_SORTITION_HEIGHT_FIELD_NUMBER: _ClassVar[int] + UNBONDING_HEIGHT_FIELD_NUMBER: _ClassVar[int] + ADDRESS_FIELD_NUMBER: _ClassVar[int] + AVAILABILITY_SCORE_FIELD_NUMBER: _ClassVar[int] + hash: str + data: str + public_key: str + number: int + stake: int + last_bonding_height: int + last_sortition_height: int + unbonding_height: int + address: str + availability_score: float + def __init__(self, hash: _Optional[str] = ..., data: _Optional[str] = ..., public_key: _Optional[str] = ..., number: _Optional[int] = ..., stake: _Optional[int] = ..., last_bonding_height: _Optional[int] = ..., last_sortition_height: _Optional[int] = ..., unbonding_height: _Optional[int] = ..., address: _Optional[str] = ..., availability_score: _Optional[float] = ...) -> None: ... + +class AccountInfo(_message.Message): + __slots__ = ("hash", "data", "number", "balance", "address") + HASH_FIELD_NUMBER: _ClassVar[int] + DATA_FIELD_NUMBER: _ClassVar[int] + NUMBER_FIELD_NUMBER: _ClassVar[int] + BALANCE_FIELD_NUMBER: _ClassVar[int] + ADDRESS_FIELD_NUMBER: _ClassVar[int] + hash: str + data: str + number: int + balance: int + address: str + def __init__(self, hash: _Optional[str] = ..., data: _Optional[str] = ..., number: _Optional[int] = ..., balance: _Optional[int] = ..., address: _Optional[str] = ...) -> None: ... + +class BlockHeaderInfo(_message.Message): + __slots__ = ("version", "prev_block_hash", "state_root", "sortition_seed", "proposer_address") + VERSION_FIELD_NUMBER: _ClassVar[int] + PREV_BLOCK_HASH_FIELD_NUMBER: _ClassVar[int] + STATE_ROOT_FIELD_NUMBER: _ClassVar[int] + SORTITION_SEED_FIELD_NUMBER: _ClassVar[int] + PROPOSER_ADDRESS_FIELD_NUMBER: _ClassVar[int] + version: int + prev_block_hash: str + state_root: str + sortition_seed: str + proposer_address: str + def __init__(self, version: _Optional[int] = ..., prev_block_hash: _Optional[str] = ..., state_root: _Optional[str] = ..., sortition_seed: _Optional[str] = ..., proposer_address: _Optional[str] = ...) -> None: ... + +class CertificateInfo(_message.Message): + __slots__ = ("hash", "round", "committers", "absentees", "signature") + HASH_FIELD_NUMBER: _ClassVar[int] + ROUND_FIELD_NUMBER: _ClassVar[int] + COMMITTERS_FIELD_NUMBER: _ClassVar[int] + ABSENTEES_FIELD_NUMBER: _ClassVar[int] + SIGNATURE_FIELD_NUMBER: _ClassVar[int] + hash: str + round: int + committers: _containers.RepeatedScalarFieldContainer[int] + absentees: _containers.RepeatedScalarFieldContainer[int] + signature: str + def __init__(self, hash: _Optional[str] = ..., round: _Optional[int] = ..., committers: _Optional[_Iterable[int]] = ..., absentees: _Optional[_Iterable[int]] = ..., signature: _Optional[str] = ...) -> None: ... + +class VoteInfo(_message.Message): + __slots__ = ("type", "voter", "block_hash", "round", "cp_round", "cp_value") + TYPE_FIELD_NUMBER: _ClassVar[int] + VOTER_FIELD_NUMBER: _ClassVar[int] + BLOCK_HASH_FIELD_NUMBER: _ClassVar[int] + ROUND_FIELD_NUMBER: _ClassVar[int] + CP_ROUND_FIELD_NUMBER: _ClassVar[int] + CP_VALUE_FIELD_NUMBER: _ClassVar[int] + type: VoteType + voter: str + block_hash: str + round: int + cp_round: int + cp_value: int + def __init__(self, type: _Optional[_Union[VoteType, str]] = ..., voter: _Optional[str] = ..., block_hash: _Optional[str] = ..., round: _Optional[int] = ..., cp_round: _Optional[int] = ..., cp_value: _Optional[int] = ...) -> None: ... + +class ConsensusInfo(_message.Message): + __slots__ = ("address", "active", "height", "round", "votes") + ADDRESS_FIELD_NUMBER: _ClassVar[int] + ACTIVE_FIELD_NUMBER: _ClassVar[int] + HEIGHT_FIELD_NUMBER: _ClassVar[int] + ROUND_FIELD_NUMBER: _ClassVar[int] + VOTES_FIELD_NUMBER: _ClassVar[int] + address: str + active: bool + height: int + round: int + votes: _containers.RepeatedCompositeFieldContainer[VoteInfo] + def __init__(self, address: _Optional[str] = ..., active: bool = ..., height: _Optional[int] = ..., round: _Optional[int] = ..., votes: _Optional[_Iterable[_Union[VoteInfo, _Mapping]]] = ...) -> None: ... diff --git a/www/grpc/gen/python/network_pb2.pyi b/www/grpc/gen/python/network_pb2.pyi new file mode 100644 index 000000000..c0145a42f --- /dev/null +++ b/www/grpc/gen/python/network_pb2.pyi @@ -0,0 +1,142 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class GetNetworkInfoRequest(_message.Message): + __slots__ = ("only_connected",) + ONLY_CONNECTED_FIELD_NUMBER: _ClassVar[int] + only_connected: bool + def __init__(self, only_connected: bool = ...) -> None: ... + +class GetNetworkInfoResponse(_message.Message): + __slots__ = ("network_name", "total_sent_bytes", "total_received_bytes", "connected_peers_count", "connected_peers", "sent_bytes", "received_bytes") + class SentBytesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: int + value: int + def __init__(self, key: _Optional[int] = ..., value: _Optional[int] = ...) -> None: ... + class ReceivedBytesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: int + value: int + def __init__(self, key: _Optional[int] = ..., value: _Optional[int] = ...) -> None: ... + NETWORK_NAME_FIELD_NUMBER: _ClassVar[int] + TOTAL_SENT_BYTES_FIELD_NUMBER: _ClassVar[int] + TOTAL_RECEIVED_BYTES_FIELD_NUMBER: _ClassVar[int] + CONNECTED_PEERS_COUNT_FIELD_NUMBER: _ClassVar[int] + CONNECTED_PEERS_FIELD_NUMBER: _ClassVar[int] + SENT_BYTES_FIELD_NUMBER: _ClassVar[int] + RECEIVED_BYTES_FIELD_NUMBER: _ClassVar[int] + network_name: str + total_sent_bytes: int + total_received_bytes: int + connected_peers_count: int + connected_peers: _containers.RepeatedCompositeFieldContainer[PeerInfo] + sent_bytes: _containers.ScalarMap[int, int] + received_bytes: _containers.ScalarMap[int, int] + def __init__(self, network_name: _Optional[str] = ..., total_sent_bytes: _Optional[int] = ..., total_received_bytes: _Optional[int] = ..., connected_peers_count: _Optional[int] = ..., connected_peers: _Optional[_Iterable[_Union[PeerInfo, _Mapping]]] = ..., sent_bytes: _Optional[_Mapping[int, int]] = ..., received_bytes: _Optional[_Mapping[int, int]] = ...) -> None: ... + +class GetNodeInfoRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class GetNodeInfoResponse(_message.Message): + __slots__ = ("moniker", "agent", "peer_id", "started_at", "reachability", "services", "services_names", "local_addrs", "protocols", "clock_offset", "connection_info") + MONIKER_FIELD_NUMBER: _ClassVar[int] + AGENT_FIELD_NUMBER: _ClassVar[int] + PEER_ID_FIELD_NUMBER: _ClassVar[int] + STARTED_AT_FIELD_NUMBER: _ClassVar[int] + REACHABILITY_FIELD_NUMBER: _ClassVar[int] + SERVICES_FIELD_NUMBER: _ClassVar[int] + SERVICES_NAMES_FIELD_NUMBER: _ClassVar[int] + LOCAL_ADDRS_FIELD_NUMBER: _ClassVar[int] + PROTOCOLS_FIELD_NUMBER: _ClassVar[int] + CLOCK_OFFSET_FIELD_NUMBER: _ClassVar[int] + CONNECTION_INFO_FIELD_NUMBER: _ClassVar[int] + moniker: str + agent: str + peer_id: str + started_at: int + reachability: str + services: int + services_names: str + local_addrs: _containers.RepeatedScalarFieldContainer[str] + protocols: _containers.RepeatedScalarFieldContainer[str] + clock_offset: float + connection_info: ConnectionInfo + def __init__(self, moniker: _Optional[str] = ..., agent: _Optional[str] = ..., peer_id: _Optional[str] = ..., started_at: _Optional[int] = ..., reachability: _Optional[str] = ..., services: _Optional[int] = ..., services_names: _Optional[str] = ..., local_addrs: _Optional[_Iterable[str]] = ..., protocols: _Optional[_Iterable[str]] = ..., clock_offset: _Optional[float] = ..., connection_info: _Optional[_Union[ConnectionInfo, _Mapping]] = ...) -> None: ... + +class PeerInfo(_message.Message): + __slots__ = ("status", "moniker", "agent", "peer_id", "consensus_keys", "consensus_addresses", "services", "last_block_hash", "height", "received_bundles", "invalid_bundles", "last_sent", "last_received", "sent_bytes", "received_bytes", "address", "direction", "protocols", "total_sessions", "completed_sessions") + class SentBytesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: int + value: int + def __init__(self, key: _Optional[int] = ..., value: _Optional[int] = ...) -> None: ... + class ReceivedBytesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: int + value: int + def __init__(self, key: _Optional[int] = ..., value: _Optional[int] = ...) -> None: ... + STATUS_FIELD_NUMBER: _ClassVar[int] + MONIKER_FIELD_NUMBER: _ClassVar[int] + AGENT_FIELD_NUMBER: _ClassVar[int] + PEER_ID_FIELD_NUMBER: _ClassVar[int] + CONSENSUS_KEYS_FIELD_NUMBER: _ClassVar[int] + CONSENSUS_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + SERVICES_FIELD_NUMBER: _ClassVar[int] + LAST_BLOCK_HASH_FIELD_NUMBER: _ClassVar[int] + HEIGHT_FIELD_NUMBER: _ClassVar[int] + RECEIVED_BUNDLES_FIELD_NUMBER: _ClassVar[int] + INVALID_BUNDLES_FIELD_NUMBER: _ClassVar[int] + LAST_SENT_FIELD_NUMBER: _ClassVar[int] + LAST_RECEIVED_FIELD_NUMBER: _ClassVar[int] + SENT_BYTES_FIELD_NUMBER: _ClassVar[int] + RECEIVED_BYTES_FIELD_NUMBER: _ClassVar[int] + ADDRESS_FIELD_NUMBER: _ClassVar[int] + DIRECTION_FIELD_NUMBER: _ClassVar[int] + PROTOCOLS_FIELD_NUMBER: _ClassVar[int] + TOTAL_SESSIONS_FIELD_NUMBER: _ClassVar[int] + COMPLETED_SESSIONS_FIELD_NUMBER: _ClassVar[int] + status: int + moniker: str + agent: str + peer_id: str + consensus_keys: _containers.RepeatedScalarFieldContainer[str] + consensus_addresses: _containers.RepeatedScalarFieldContainer[str] + services: int + last_block_hash: str + height: int + received_bundles: int + invalid_bundles: int + last_sent: int + last_received: int + sent_bytes: _containers.ScalarMap[int, int] + received_bytes: _containers.ScalarMap[int, int] + address: str + direction: str + protocols: _containers.RepeatedScalarFieldContainer[str] + total_sessions: int + completed_sessions: int + def __init__(self, status: _Optional[int] = ..., moniker: _Optional[str] = ..., agent: _Optional[str] = ..., peer_id: _Optional[str] = ..., consensus_keys: _Optional[_Iterable[str]] = ..., consensus_addresses: _Optional[_Iterable[str]] = ..., services: _Optional[int] = ..., last_block_hash: _Optional[str] = ..., height: _Optional[int] = ..., received_bundles: _Optional[int] = ..., invalid_bundles: _Optional[int] = ..., last_sent: _Optional[int] = ..., last_received: _Optional[int] = ..., sent_bytes: _Optional[_Mapping[int, int]] = ..., received_bytes: _Optional[_Mapping[int, int]] = ..., address: _Optional[str] = ..., direction: _Optional[str] = ..., protocols: _Optional[_Iterable[str]] = ..., total_sessions: _Optional[int] = ..., completed_sessions: _Optional[int] = ...) -> None: ... + +class ConnectionInfo(_message.Message): + __slots__ = ("connections", "inbound_connections", "outbound_connections") + CONNECTIONS_FIELD_NUMBER: _ClassVar[int] + INBOUND_CONNECTIONS_FIELD_NUMBER: _ClassVar[int] + OUTBOUND_CONNECTIONS_FIELD_NUMBER: _ClassVar[int] + connections: int + inbound_connections: int + outbound_connections: int + def __init__(self, connections: _Optional[int] = ..., inbound_connections: _Optional[int] = ..., outbound_connections: _Optional[int] = ...) -> None: ... diff --git a/www/grpc/gen/python/transaction_pb2.pyi b/www/grpc/gen/python/transaction_pb2.pyi new file mode 100644 index 000000000..ac8d9ef60 --- /dev/null +++ b/www/grpc/gen/python/transaction_pb2.pyi @@ -0,0 +1,219 @@ +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class PayloadType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + UNKNOWN: _ClassVar[PayloadType] + TRANSFER_PAYLOAD: _ClassVar[PayloadType] + BOND_PAYLOAD: _ClassVar[PayloadType] + SORTITION_PAYLOAD: _ClassVar[PayloadType] + UNBOND_PAYLOAD: _ClassVar[PayloadType] + WITHDRAW_PAYLOAD: _ClassVar[PayloadType] + +class TransactionVerbosity(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + TRANSACTION_DATA: _ClassVar[TransactionVerbosity] + TRANSACTION_INFO: _ClassVar[TransactionVerbosity] +UNKNOWN: PayloadType +TRANSFER_PAYLOAD: PayloadType +BOND_PAYLOAD: PayloadType +SORTITION_PAYLOAD: PayloadType +UNBOND_PAYLOAD: PayloadType +WITHDRAW_PAYLOAD: PayloadType +TRANSACTION_DATA: TransactionVerbosity +TRANSACTION_INFO: TransactionVerbosity + +class GetTransactionRequest(_message.Message): + __slots__ = ("id", "verbosity") + ID_FIELD_NUMBER: _ClassVar[int] + VERBOSITY_FIELD_NUMBER: _ClassVar[int] + id: str + verbosity: TransactionVerbosity + def __init__(self, id: _Optional[str] = ..., verbosity: _Optional[_Union[TransactionVerbosity, str]] = ...) -> None: ... + +class GetTransactionResponse(_message.Message): + __slots__ = ("block_height", "block_time", "transaction") + BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] + BLOCK_TIME_FIELD_NUMBER: _ClassVar[int] + TRANSACTION_FIELD_NUMBER: _ClassVar[int] + block_height: int + block_time: int + transaction: TransactionInfo + def __init__(self, block_height: _Optional[int] = ..., block_time: _Optional[int] = ..., transaction: _Optional[_Union[TransactionInfo, _Mapping]] = ...) -> None: ... + +class CalculateFeeRequest(_message.Message): + __slots__ = ("amount", "payload_type", "fixed_amount") + AMOUNT_FIELD_NUMBER: _ClassVar[int] + PAYLOAD_TYPE_FIELD_NUMBER: _ClassVar[int] + FIXED_AMOUNT_FIELD_NUMBER: _ClassVar[int] + amount: int + payload_type: PayloadType + fixed_amount: bool + def __init__(self, amount: _Optional[int] = ..., payload_type: _Optional[_Union[PayloadType, str]] = ..., fixed_amount: bool = ...) -> None: ... + +class CalculateFeeResponse(_message.Message): + __slots__ = ("amount", "fee") + AMOUNT_FIELD_NUMBER: _ClassVar[int] + FEE_FIELD_NUMBER: _ClassVar[int] + amount: int + fee: int + def __init__(self, amount: _Optional[int] = ..., fee: _Optional[int] = ...) -> None: ... + +class BroadcastTransactionRequest(_message.Message): + __slots__ = ("signed_raw_transaction",) + SIGNED_RAW_TRANSACTION_FIELD_NUMBER: _ClassVar[int] + signed_raw_transaction: str + def __init__(self, signed_raw_transaction: _Optional[str] = ...) -> None: ... + +class BroadcastTransactionResponse(_message.Message): + __slots__ = ("id",) + ID_FIELD_NUMBER: _ClassVar[int] + id: str + def __init__(self, id: _Optional[str] = ...) -> None: ... + +class GetRawTransferTransactionRequest(_message.Message): + __slots__ = ("lock_time", "sender", "receiver", "amount", "fee", "memo") + LOCK_TIME_FIELD_NUMBER: _ClassVar[int] + SENDER_FIELD_NUMBER: _ClassVar[int] + RECEIVER_FIELD_NUMBER: _ClassVar[int] + AMOUNT_FIELD_NUMBER: _ClassVar[int] + FEE_FIELD_NUMBER: _ClassVar[int] + MEMO_FIELD_NUMBER: _ClassVar[int] + lock_time: int + sender: str + receiver: str + amount: int + fee: int + memo: str + def __init__(self, lock_time: _Optional[int] = ..., sender: _Optional[str] = ..., receiver: _Optional[str] = ..., amount: _Optional[int] = ..., fee: _Optional[int] = ..., memo: _Optional[str] = ...) -> None: ... + +class GetRawBondTransactionRequest(_message.Message): + __slots__ = ("lock_time", "sender", "receiver", "stake", "public_key", "fee", "memo") + LOCK_TIME_FIELD_NUMBER: _ClassVar[int] + SENDER_FIELD_NUMBER: _ClassVar[int] + RECEIVER_FIELD_NUMBER: _ClassVar[int] + STAKE_FIELD_NUMBER: _ClassVar[int] + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + FEE_FIELD_NUMBER: _ClassVar[int] + MEMO_FIELD_NUMBER: _ClassVar[int] + lock_time: int + sender: str + receiver: str + stake: int + public_key: str + fee: int + memo: str + def __init__(self, lock_time: _Optional[int] = ..., sender: _Optional[str] = ..., receiver: _Optional[str] = ..., stake: _Optional[int] = ..., public_key: _Optional[str] = ..., fee: _Optional[int] = ..., memo: _Optional[str] = ...) -> None: ... + +class GetRawUnbondTransactionRequest(_message.Message): + __slots__ = ("lock_time", "validator_address", "memo") + LOCK_TIME_FIELD_NUMBER: _ClassVar[int] + VALIDATOR_ADDRESS_FIELD_NUMBER: _ClassVar[int] + MEMO_FIELD_NUMBER: _ClassVar[int] + lock_time: int + validator_address: str + memo: str + def __init__(self, lock_time: _Optional[int] = ..., validator_address: _Optional[str] = ..., memo: _Optional[str] = ...) -> None: ... + +class GetRawWithdrawTransactionRequest(_message.Message): + __slots__ = ("lock_time", "validator_address", "account_address", "amount", "fee", "memo") + LOCK_TIME_FIELD_NUMBER: _ClassVar[int] + VALIDATOR_ADDRESS_FIELD_NUMBER: _ClassVar[int] + ACCOUNT_ADDRESS_FIELD_NUMBER: _ClassVar[int] + AMOUNT_FIELD_NUMBER: _ClassVar[int] + FEE_FIELD_NUMBER: _ClassVar[int] + MEMO_FIELD_NUMBER: _ClassVar[int] + lock_time: int + validator_address: str + account_address: str + amount: int + fee: int + memo: str + def __init__(self, lock_time: _Optional[int] = ..., validator_address: _Optional[str] = ..., account_address: _Optional[str] = ..., amount: _Optional[int] = ..., fee: _Optional[int] = ..., memo: _Optional[str] = ...) -> None: ... + +class GetRawTransactionResponse(_message.Message): + __slots__ = ("raw_transaction",) + RAW_TRANSACTION_FIELD_NUMBER: _ClassVar[int] + raw_transaction: str + def __init__(self, raw_transaction: _Optional[str] = ...) -> None: ... + +class PayloadTransfer(_message.Message): + __slots__ = ("sender", "receiver", "amount") + SENDER_FIELD_NUMBER: _ClassVar[int] + RECEIVER_FIELD_NUMBER: _ClassVar[int] + AMOUNT_FIELD_NUMBER: _ClassVar[int] + sender: str + receiver: str + amount: int + def __init__(self, sender: _Optional[str] = ..., receiver: _Optional[str] = ..., amount: _Optional[int] = ...) -> None: ... + +class PayloadBond(_message.Message): + __slots__ = ("sender", "receiver", "stake") + SENDER_FIELD_NUMBER: _ClassVar[int] + RECEIVER_FIELD_NUMBER: _ClassVar[int] + STAKE_FIELD_NUMBER: _ClassVar[int] + sender: str + receiver: str + stake: int + def __init__(self, sender: _Optional[str] = ..., receiver: _Optional[str] = ..., stake: _Optional[int] = ...) -> None: ... + +class PayloadSortition(_message.Message): + __slots__ = ("address", "proof") + ADDRESS_FIELD_NUMBER: _ClassVar[int] + PROOF_FIELD_NUMBER: _ClassVar[int] + address: str + proof: str + def __init__(self, address: _Optional[str] = ..., proof: _Optional[str] = ...) -> None: ... + +class PayloadUnbond(_message.Message): + __slots__ = ("validator",) + VALIDATOR_FIELD_NUMBER: _ClassVar[int] + validator: str + def __init__(self, validator: _Optional[str] = ...) -> None: ... + +class PayloadWithdraw(_message.Message): + __slots__ = ("to", "amount") + FROM_FIELD_NUMBER: _ClassVar[int] + TO_FIELD_NUMBER: _ClassVar[int] + AMOUNT_FIELD_NUMBER: _ClassVar[int] + to: str + amount: int + def __init__(self, to: _Optional[str] = ..., amount: _Optional[int] = ..., **kwargs) -> None: ... + +class TransactionInfo(_message.Message): + __slots__ = ("id", "data", "version", "lock_time", "value", "fee", "payload_type", "transfer", "bond", "sortition", "unbond", "withdraw", "memo", "public_key", "signature") + ID_FIELD_NUMBER: _ClassVar[int] + DATA_FIELD_NUMBER: _ClassVar[int] + VERSION_FIELD_NUMBER: _ClassVar[int] + LOCK_TIME_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + FEE_FIELD_NUMBER: _ClassVar[int] + PAYLOAD_TYPE_FIELD_NUMBER: _ClassVar[int] + TRANSFER_FIELD_NUMBER: _ClassVar[int] + BOND_FIELD_NUMBER: _ClassVar[int] + SORTITION_FIELD_NUMBER: _ClassVar[int] + UNBOND_FIELD_NUMBER: _ClassVar[int] + WITHDRAW_FIELD_NUMBER: _ClassVar[int] + MEMO_FIELD_NUMBER: _ClassVar[int] + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + SIGNATURE_FIELD_NUMBER: _ClassVar[int] + id: str + data: str + version: int + lock_time: int + value: int + fee: int + payload_type: PayloadType + transfer: PayloadTransfer + bond: PayloadBond + sortition: PayloadSortition + unbond: PayloadUnbond + withdraw: PayloadWithdraw + memo: str + public_key: str + signature: str + def __init__(self, id: _Optional[str] = ..., data: _Optional[str] = ..., version: _Optional[int] = ..., lock_time: _Optional[int] = ..., value: _Optional[int] = ..., fee: _Optional[int] = ..., payload_type: _Optional[_Union[PayloadType, str]] = ..., transfer: _Optional[_Union[PayloadTransfer, _Mapping]] = ..., bond: _Optional[_Union[PayloadBond, _Mapping]] = ..., sortition: _Optional[_Union[PayloadSortition, _Mapping]] = ..., unbond: _Optional[_Union[PayloadUnbond, _Mapping]] = ..., withdraw: _Optional[_Union[PayloadWithdraw, _Mapping]] = ..., memo: _Optional[str] = ..., public_key: _Optional[str] = ..., signature: _Optional[str] = ...) -> None: ... diff --git a/www/grpc/gen/python/utils_pb2.pyi b/www/grpc/gen/python/utils_pb2.pyi new file mode 100644 index 000000000..0bfaf6e53 --- /dev/null +++ b/www/grpc/gen/python/utils_pb2.pyi @@ -0,0 +1,35 @@ +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Optional as _Optional + +DESCRIPTOR: _descriptor.FileDescriptor + +class SignMessageWithPrivateKeyRequest(_message.Message): + __slots__ = ("private_key", "message") + PRIVATE_KEY_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + private_key: str + message: str + def __init__(self, private_key: _Optional[str] = ..., message: _Optional[str] = ...) -> None: ... + +class SignMessageWithPrivateKeyResponse(_message.Message): + __slots__ = ("signature",) + SIGNATURE_FIELD_NUMBER: _ClassVar[int] + signature: str + def __init__(self, signature: _Optional[str] = ...) -> None: ... + +class VerifyMessageRequest(_message.Message): + __slots__ = ("message", "signature", "public_key") + MESSAGE_FIELD_NUMBER: _ClassVar[int] + SIGNATURE_FIELD_NUMBER: _ClassVar[int] + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + message: str + signature: str + public_key: str + def __init__(self, message: _Optional[str] = ..., signature: _Optional[str] = ..., public_key: _Optional[str] = ...) -> None: ... + +class VerifyMessageResponse(_message.Message): + __slots__ = ("is_valid",) + IS_VALID_FIELD_NUMBER: _ClassVar[int] + is_valid: bool + def __init__(self, is_valid: bool = ...) -> None: ... diff --git a/www/grpc/gen/python/wallet_pb2.pyi b/www/grpc/gen/python/wallet_pb2.pyi new file mode 100644 index 000000000..023fad277 --- /dev/null +++ b/www/grpc/gen/python/wallet_pb2.pyi @@ -0,0 +1,191 @@ +import transaction_pb2 as _transaction_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class AddressType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ADDRESS_TYPE_TREASURY: _ClassVar[AddressType] + ADDRESS_TYPE_VALIDATOR: _ClassVar[AddressType] + ADDRESS_TYPE_BLS_ACCOUNT: _ClassVar[AddressType] +ADDRESS_TYPE_TREASURY: AddressType +ADDRESS_TYPE_VALIDATOR: AddressType +ADDRESS_TYPE_BLS_ACCOUNT: AddressType + +class AddressInfo(_message.Message): + __slots__ = ("address", "public_key", "label", "path") + ADDRESS_FIELD_NUMBER: _ClassVar[int] + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + LABEL_FIELD_NUMBER: _ClassVar[int] + PATH_FIELD_NUMBER: _ClassVar[int] + address: str + public_key: str + label: str + path: str + def __init__(self, address: _Optional[str] = ..., public_key: _Optional[str] = ..., label: _Optional[str] = ..., path: _Optional[str] = ...) -> None: ... + +class HistoryInfo(_message.Message): + __slots__ = ("transaction_id", "time", "payload_type", "description", "amount") + TRANSACTION_ID_FIELD_NUMBER: _ClassVar[int] + TIME_FIELD_NUMBER: _ClassVar[int] + PAYLOAD_TYPE_FIELD_NUMBER: _ClassVar[int] + DESCRIPTION_FIELD_NUMBER: _ClassVar[int] + AMOUNT_FIELD_NUMBER: _ClassVar[int] + transaction_id: str + time: int + payload_type: str + description: str + amount: int + def __init__(self, transaction_id: _Optional[str] = ..., time: _Optional[int] = ..., payload_type: _Optional[str] = ..., description: _Optional[str] = ..., amount: _Optional[int] = ...) -> None: ... + +class GetAddressHistoryRequest(_message.Message): + __slots__ = ("wallet_name", "address") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + ADDRESS_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + address: str + def __init__(self, wallet_name: _Optional[str] = ..., address: _Optional[str] = ...) -> None: ... + +class GetAddressHistoryResponse(_message.Message): + __slots__ = ("history_info",) + HISTORY_INFO_FIELD_NUMBER: _ClassVar[int] + history_info: _containers.RepeatedCompositeFieldContainer[HistoryInfo] + def __init__(self, history_info: _Optional[_Iterable[_Union[HistoryInfo, _Mapping]]] = ...) -> None: ... + +class GetNewAddressRequest(_message.Message): + __slots__ = ("wallet_name", "address_type", "label") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + ADDRESS_TYPE_FIELD_NUMBER: _ClassVar[int] + LABEL_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + address_type: AddressType + label: str + def __init__(self, wallet_name: _Optional[str] = ..., address_type: _Optional[_Union[AddressType, str]] = ..., label: _Optional[str] = ...) -> None: ... + +class GetNewAddressResponse(_message.Message): + __slots__ = ("wallet_name", "address_info") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + ADDRESS_INFO_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + address_info: AddressInfo + def __init__(self, wallet_name: _Optional[str] = ..., address_info: _Optional[_Union[AddressInfo, _Mapping]] = ...) -> None: ... + +class RestoreWalletRequest(_message.Message): + __slots__ = ("wallet_name", "mnemonic", "password") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + MNEMONIC_FIELD_NUMBER: _ClassVar[int] + PASSWORD_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + mnemonic: str + password: str + def __init__(self, wallet_name: _Optional[str] = ..., mnemonic: _Optional[str] = ..., password: _Optional[str] = ...) -> None: ... + +class RestoreWalletResponse(_message.Message): + __slots__ = ("wallet_name",) + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + def __init__(self, wallet_name: _Optional[str] = ...) -> None: ... + +class CreateWalletRequest(_message.Message): + __slots__ = ("wallet_name", "password") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + PASSWORD_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + password: str + def __init__(self, wallet_name: _Optional[str] = ..., password: _Optional[str] = ...) -> None: ... + +class CreateWalletResponse(_message.Message): + __slots__ = ("mnemonic",) + MNEMONIC_FIELD_NUMBER: _ClassVar[int] + mnemonic: str + def __init__(self, mnemonic: _Optional[str] = ...) -> None: ... + +class LoadWalletRequest(_message.Message): + __slots__ = ("wallet_name",) + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + def __init__(self, wallet_name: _Optional[str] = ...) -> None: ... + +class LoadWalletResponse(_message.Message): + __slots__ = ("wallet_name",) + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + def __init__(self, wallet_name: _Optional[str] = ...) -> None: ... + +class UnloadWalletRequest(_message.Message): + __slots__ = ("wallet_name",) + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + def __init__(self, wallet_name: _Optional[str] = ...) -> None: ... + +class UnloadWalletResponse(_message.Message): + __slots__ = ("wallet_name",) + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + def __init__(self, wallet_name: _Optional[str] = ...) -> None: ... + +class GetValidatorAddressRequest(_message.Message): + __slots__ = ("public_key",) + PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] + public_key: str + def __init__(self, public_key: _Optional[str] = ...) -> None: ... + +class GetValidatorAddressResponse(_message.Message): + __slots__ = ("address",) + ADDRESS_FIELD_NUMBER: _ClassVar[int] + address: str + def __init__(self, address: _Optional[str] = ...) -> None: ... + +class SignRawTransactionRequest(_message.Message): + __slots__ = ("wallet_name", "raw_transaction", "password") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + RAW_TRANSACTION_FIELD_NUMBER: _ClassVar[int] + PASSWORD_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + raw_transaction: str + password: str + def __init__(self, wallet_name: _Optional[str] = ..., raw_transaction: _Optional[str] = ..., password: _Optional[str] = ...) -> None: ... + +class SignRawTransactionResponse(_message.Message): + __slots__ = ("transaction_id", "signed_raw_transaction") + TRANSACTION_ID_FIELD_NUMBER: _ClassVar[int] + SIGNED_RAW_TRANSACTION_FIELD_NUMBER: _ClassVar[int] + transaction_id: str + signed_raw_transaction: str + def __init__(self, transaction_id: _Optional[str] = ..., signed_raw_transaction: _Optional[str] = ...) -> None: ... + +class GetTotalBalanceRequest(_message.Message): + __slots__ = ("wallet_name",) + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + def __init__(self, wallet_name: _Optional[str] = ...) -> None: ... + +class GetTotalBalanceResponse(_message.Message): + __slots__ = ("wallet_name", "total_balance") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + TOTAL_BALANCE_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + total_balance: int + def __init__(self, wallet_name: _Optional[str] = ..., total_balance: _Optional[int] = ...) -> None: ... + +class SignMessageRequest(_message.Message): + __slots__ = ("wallet_name", "password", "address", "message") + WALLET_NAME_FIELD_NUMBER: _ClassVar[int] + PASSWORD_FIELD_NUMBER: _ClassVar[int] + ADDRESS_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + wallet_name: str + password: str + address: str + message: str + def __init__(self, wallet_name: _Optional[str] = ..., password: _Optional[str] = ..., address: _Optional[str] = ..., message: _Optional[str] = ...) -> None: ... + +class SignMessageResponse(_message.Message): + __slots__ = ("signature",) + SIGNATURE_FIELD_NUMBER: _ClassVar[int] + signature: str + def __init__(self, signature: _Optional[str] = ...) -> None: ... From 4eb53357ca110754015d1ebc54706a28e73b11b9 Mon Sep 17 00:00:00 2001 From: K Date: Thu, 22 Aug 2024 10:23:56 +0330 Subject: [PATCH 14/25] feat(crypto): supporting ed25519 (#1481) --- crypto/address.go | 3 +- crypto/bls/hdkeychain/errors.go | 3 + crypto/bls/hdkeychain/extendedkey.go | 10 +- crypto/bls/hdkeychain/extendedkey_test.go | 88 ++++- crypto/bls/private_key.go | 4 +- crypto/bls/public_key.go | 5 +- crypto/bls/signature.go | 5 +- crypto/ed25519/ed25519.go | 1 + crypto/ed25519/ed25519_test.go | 186 +++++++++++ crypto/ed25519/errors.go | 1 + crypto/ed25519/hdkeychain/errors.go | 24 ++ crypto/ed25519/hdkeychain/extendedkey.go | 279 ++++++++++++++++ crypto/ed25519/hdkeychain/extendedkey_test.go | 314 ++++++++++++++++++ crypto/ed25519/private_key.go | 108 ++++++ crypto/ed25519/private_key_test.go | 105 ++++++ crypto/ed25519/public_key.go | 146 ++++++++ crypto/ed25519/public_key_test.go | 233 +++++++++++++ crypto/ed25519/signature.go | 91 +++++ crypto/ed25519/signature_test.go | 178 ++++++++++ util/testsuite/testsuite.go | 14 + 20 files changed, 1780 insertions(+), 18 deletions(-) create mode 100644 crypto/ed25519/ed25519.go create mode 100644 crypto/ed25519/ed25519_test.go create mode 100644 crypto/ed25519/errors.go create mode 100644 crypto/ed25519/hdkeychain/errors.go create mode 100644 crypto/ed25519/hdkeychain/extendedkey.go create mode 100644 crypto/ed25519/hdkeychain/extendedkey_test.go create mode 100644 crypto/ed25519/private_key.go create mode 100644 crypto/ed25519/private_key_test.go create mode 100644 crypto/ed25519/public_key.go create mode 100644 crypto/ed25519/public_key_test.go create mode 100644 crypto/ed25519/signature.go create mode 100644 crypto/ed25519/signature_test.go diff --git a/crypto/address.go b/crypto/address.go index 1a79762e1..06c450d28 100644 --- a/crypto/address.go +++ b/crypto/address.go @@ -20,7 +20,8 @@ const ( ) const ( - SignatureTypeBLS byte = 1 + SignatureTypeBLS byte = 1 + SignatureTypeEd25519 byte = 3 ) const ( diff --git a/crypto/bls/hdkeychain/errors.go b/crypto/bls/hdkeychain/errors.go index 110dfad53..a644ee6eb 100644 --- a/crypto/bls/hdkeychain/errors.go +++ b/crypto/bls/hdkeychain/errors.go @@ -30,4 +30,7 @@ var ( // ErrInvalidKeyData describes an error in which the provided key is // not valid. ErrInvalidKeyData = errors.New("key data is invalid") + + // ErrInvalidHRP describes an error in which the HRP is not valid. + ErrInvalidHRP = errors.New("HRP is invalid") ) diff --git a/crypto/bls/hdkeychain/extendedkey.go b/crypto/bls/hdkeychain/extendedkey.go index 34fd8c715..087c272a0 100644 --- a/crypto/bls/hdkeychain/extendedkey.go +++ b/crypto/bls/hdkeychain/extendedkey.go @@ -1,7 +1,7 @@ package hdkeychain // References: -// [PIP-11]: Deterministic key hierarchy for BLS12-381 curve +// PIP-11: Deterministic key hierarchy for BLS12-381 curve // https://pips.pactus.org/PIPs/pip-11 import ( @@ -448,9 +448,13 @@ func NewKeyFromString(str string) (*ExtendedKey, error) { return nil, err } - isPrivate := true - if hrp == crypto.XPublicKeyHRP { + var isPrivate bool + if hrp == crypto.XPrivateKeyHRP { + isPrivate = true + } else if hrp == crypto.XPublicKeyHRP { isPrivate = false + } else { + return nil, ErrInvalidHRP } return newExtendedKey(key, chainCode, path, isPrivate, pubOnG1), nil diff --git a/crypto/bls/hdkeychain/extendedkey_test.go b/crypto/bls/hdkeychain/extendedkey_test.go index 1932ed978..478fc1690 100644 --- a/crypto/bls/hdkeychain/extendedkey_test.go +++ b/crypto/bls/hdkeychain/extendedkey_test.go @@ -255,12 +255,77 @@ func TestGenerateSeed(t *testing.T) { seed, err := GenerateSeed(test.length) assert.ErrorIs(t, err, test.err) - if test.err == nil && len(seed) != int(test.length) { - t.Errorf("GenerateSeed #%d (%s): length mismatch -- "+ - "got %d, want %d", i, test.name, len(seed), - test.length) + if test.err == nil { + assert.Len(t, seed, int(test.length), + "GenerateSeed #%d (%s): length mismatch -- got %d, want %d", + i, test.name, len(seed), test.length) + } + } +} + +// TestNewMaster ensures the NewMaster function works as intended. +func TestNewMaster(t *testing.T) { + tests := []struct { + name string + seed string + privKey string + err error + }{ + // Test various valid seeds. + { + name: "16 bytes", + seed: "000102030405060708090a0b0c0d0e0f", + privKey: "4f55e31ee1c4f58af0840fd3f5e635fd6c07eacd14283c45d7d43729003abb84", + }, + { + name: "32 bytes", + seed: "3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678", + privKey: "4c101174339ffca5cc0afca5d2d8e2538834781318e5e1c8afdabf7e6fb77444", + }, + { + name: "64 bytes", + seed: "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7" + + "b7875726f6c696663605d5a5754514e4b484542", + privKey: "47b660cc8dc2d4dc2cdf8893048bda9d5dc6318eb31f301b272b291b26cb20a1", + }, + + // Test invalid seeds. + { + name: "empty seed", + seed: "", + err: ErrInvalidSeedLen, + }, + { + name: "15 bytes", + seed: "000000000000000000000000000000", + err: ErrInvalidSeedLen, + }, + { + name: "65 bytes", + seed: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000", + err: ErrInvalidSeedLen, + }, + } + + for i, test := range tests { + seed, _ := hex.DecodeString(test.seed) + extKeyG1, err := NewMaster(seed, true) + assert.ErrorIs(t, err, test.err) + + extKeyG2, err := NewMaster(seed, true) + assert.ErrorIs(t, err, test.err) + + if test.err == nil { + privKeyG1, _ := extKeyG1.RawPrivateKey() + assert.Equal(t, test.privKey, hex.EncodeToString(privKeyG1), + "NewMaster #%d (%s): privKeyG1 mismatch -- got %x, want %s", + i+1, test.name, privKeyG1, test.privKey) - continue + privKeyG2, _ := extKeyG2.RawPrivateKey() + assert.Equal(t, test.privKey, hex.EncodeToString(privKeyG2), + "NewMaster #%d (%s): privKeyG2 mismatch -- got %x, want %s", + i+1, test.name, privKeyG2, test.privKey) } } } @@ -411,12 +476,19 @@ func TestInvalidString(t *testing.T) { expectedError: ErrInvalidKeyData, }, { - str: "SECRET1ZQ5QQQQYQQYQQQQQZQQQGQQSQQQQQPJ568VS9LZ67JKWW0P6TQY9NY58LV0PCVRQQTAEMKGV6ULJNS99Y68JHCVGPYPZTWSAST8PWFJMJQDU0FU8D4YMF58CZ998PGRN29EZYHLWNDVDDJE7XP6L", + desc: "invalid type", + str: "XPUBLIC1ZQ5QQQQYQQYQQQQQZQQQGQQSQQQQQPJ568VS9LZ67JKWW0P6TQY9NY58LV0PCVRQQTAEMKGV6ULJNS99Y68JHCVGPYPZTWSAST8PWFJMJQDU0FU8D4YMF58CZ998PGRN29EZYHLWNDVDDJ3HALEC", expectedError: ErrInvalidKeyData, }, { - str: "XPUBLIC1ZQ5QQQQYQQYQQQQQZQQQGQQSQQQQQPJ568VS9LZ67JKWW0P6TQY9NY58LV0PCVRQQTAEMKGV6ULJNS99Y68JHCVGPYPZTWSAST8PWFJMJQDU0FU8D4YMF58CZ998PGRN29EZYHLWNDVDDJ3HALEC", - expectedError: ErrInvalidKeyData, + desc: "invalid hrp", + str: "SECRET1PQ5QQQQYQQYQQQQQZQQQGQQSQQQQQPJ568VS9LZ67JKWW0P6TQY9NY58LV0PCVRQQTAEMKGV6ULJNS99Y68JHCVGPYPZTWSAST8PWFJMJQDU0FU8D4YMF58CZ998PGRN29EZYHLWNDVDDJ98PYV5", + expectedError: ErrInvalidHRP, + }, + { + desc: "invalid hrp", + str: "PUBLIC1PQ5QQQQYQQYQQQQQZQQQGQQSQQQQQPJ568VS9LZ67JKWW0P6TQY9NY58LV0PCVRQQTAEMKGV6ULJNS99Y68JHCVGPYPZTWSAST8PWFJMJQDU0FU8D4YMF58CZ998PGRN29EZYHLWNDVDDJ4Z2HK2", + expectedError: ErrInvalidHRP, }, } diff --git a/crypto/bls/private_key.go b/crypto/bls/private_key.go index 456940f0a..f0f8a5680 100644 --- a/crypto/bls/private_key.go +++ b/crypto/bls/private_key.go @@ -160,6 +160,6 @@ func (prv *PrivateKey) PublicKey() crypto.PublicKey { return prv.PublicKeyNative() } -func (prv *PrivateKey) EqualsTo(right crypto.PrivateKey) bool { - return prv.fr.Equal(&right.(*PrivateKey).fr) +func (prv *PrivateKey) EqualsTo(x crypto.PrivateKey) bool { + return prv.fr.Equal(&x.(*PrivateKey).fr) } diff --git a/crypto/bls/public_key.go b/crypto/bls/public_key.go index 722ac3a87..63b4c0157 100644 --- a/crypto/bls/public_key.go +++ b/crypto/bls/public_key.go @@ -2,6 +2,7 @@ package bls import ( "bytes" + "crypto/subtle" "fmt" "io" @@ -139,8 +140,8 @@ func (pub *PublicKey) Verify(msg []byte, sig crypto.Signature) error { } // EqualsTo checks if the current public key is equal to another public key. -func (pub *PublicKey) EqualsTo(right crypto.PublicKey) bool { - return bytes.Equal(pub.data, right.(*PublicKey).data) +func (pub *PublicKey) EqualsTo(x crypto.PublicKey) bool { + return subtle.ConstantTimeCompare(pub.data, x.(*PublicKey).data) == 1 } // AccountAddress returns the account address derived from the public key. diff --git a/crypto/bls/signature.go b/crypto/bls/signature.go index 1ceccfe66..2cf6c1c8b 100644 --- a/crypto/bls/signature.go +++ b/crypto/bls/signature.go @@ -2,6 +2,7 @@ package bls import ( "bytes" + "crypto/subtle" "encoding/hex" "fmt" "io" @@ -88,8 +89,8 @@ func (sig *Signature) Decode(r io.Reader) error { } // EqualsTo checks if the current signature is equal to another signature. -func (sig *Signature) EqualsTo(right crypto.Signature) bool { - return bytes.Equal(sig.data, right.(*Signature).data) +func (sig *Signature) EqualsTo(x crypto.Signature) bool { + return subtle.ConstantTimeCompare(sig.data, x.(*Signature).data) == 1 } // PointG1 returns the point on G1 for the signature. diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go new file mode 100644 index 000000000..21984ca9c --- /dev/null +++ b/crypto/ed25519/ed25519.go @@ -0,0 +1 @@ +package ed25519 diff --git a/crypto/ed25519/ed25519_test.go b/crypto/ed25519/ed25519_test.go new file mode 100644 index 000000000..6a065c139 --- /dev/null +++ b/crypto/ed25519/ed25519_test.go @@ -0,0 +1,186 @@ +package ed25519_test + +import ( + "encoding/hex" + "testing" + + bls12381 "github.com/kilic/bls12-381" + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" +) + +func TestSigning(t *testing.T) { + msg := []byte("zarb") + prv, _ := bls.PrivateKeyFromString( + "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67") + pub, _ := bls.PublicKeyFromString( + "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + + "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a") + sig, _ := bls.SignatureFromString( + "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792") + addr, _ := crypto.AddressFromString("pc1p5x2a0lkt5nrrdqe0rkcv6r4pfkmdhrr3xk73tq") + + sig1 := prv.Sign(msg) + assert.Equal(t, sig.Bytes(), sig1.Bytes()) + assert.NoError(t, pub.Verify(msg, sig)) + assert.Equal(t, pub, prv.PublicKey()) + assert.Equal(t, addr, pub.ValidatorAddress()) +} + +func TestSignatureAggregate(t *testing.T) { + msg := []byte("zarb") + prv1, _ := bls.PrivateKeyFromString( + "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67") + prv2, _ := bls.PrivateKeyFromString( + "SECRET1PDUV97560CWDGW2DR453YPUT84REN04G0DZFAPJQL5DV0CKDAN75QCJEV6F") + agg, _ := bls.SignatureFromString( + "a390ffec7061827b7e89193a26841dd9e3537b5db0af55661b624e8b93b855e9f65278850002ea72fb3098e674220eca") + sig1 := prv1.Sign(msg).(*bls.Signature) + sig2 := prv2.Sign(msg).(*bls.Signature) + + assert.True(t, bls.SignatureAggregate(sig1, sig2).EqualsTo(agg)) + assert.False(t, prv1.EqualsTo(prv2)) +} + +func TestAggregateFailed(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, prv1 := ts.RandBLSKeyPair() + pub2, prv2 := ts.RandBLSKeyPair() + pub3, prv3 := ts.RandBLSKeyPair() + pub4, prv4 := ts.RandBLSKeyPair() + msg1 := []byte("zarb") + msg2 := []byte("zarb0") + + sig1 := prv1.Sign(msg1).(*bls.Signature) + sig11 := prv1.Sign(msg2).(*bls.Signature) + sig2 := prv2.Sign(msg1).(*bls.Signature) + sig3 := prv3.Sign(msg1).(*bls.Signature) + sig4 := prv4.Sign(msg1).(*bls.Signature) + + agg1 := bls.SignatureAggregate(sig1, sig2, sig3) + agg2 := bls.SignatureAggregate(sig1, sig2, sig4) + agg3 := bls.SignatureAggregate(sig11, sig2, sig3) + agg4 := bls.SignatureAggregate(sig1, sig2) + agg5 := bls.SignatureAggregate(sig3, sig2, sig1) + + pubs1 := []*bls.PublicKey{pub1, pub2, pub3} + pubs2 := []*bls.PublicKey{pub1, pub2, pub4} + pubs3 := []*bls.PublicKey{pub1, pub2} + pubs4 := []*bls.PublicKey{pub3, pub2, pub1} + + pubAgg1 := bls.PublicKeyAggregate(pubs1...) + pubAgg2 := bls.PublicKeyAggregate(pubs2...) + pubAgg3 := bls.PublicKeyAggregate(pubs3...) + pubAgg4 := bls.PublicKeyAggregate(pubs4...) + + assert.NoError(t, pub1.Verify(msg1, sig1)) + assert.NoError(t, pub2.Verify(msg1, sig2)) + assert.NoError(t, pub3.Verify(msg1, sig3)) + assert.Error(t, pub2.Verify(msg1, sig1)) + assert.Error(t, pub3.Verify(msg1, sig1)) + assert.Error(t, pub1.Verify(msg1, agg1)) + assert.Error(t, pub2.Verify(msg1, agg1)) + assert.Error(t, pub3.Verify(msg1, agg1)) + + assert.NoError(t, pubAgg1.Verify(msg1, agg1)) + assert.Error(t, pubAgg1.Verify(msg2, agg1)) + assert.Error(t, pubAgg1.Verify(msg1, agg2)) + assert.Error(t, pubAgg2.Verify(msg1, agg1)) + assert.NoError(t, pubAgg2.Verify(msg1, agg2)) + assert.Error(t, pubAgg2.Verify(msg2, agg2)) + assert.Error(t, pubAgg1.Verify(msg1, agg3)) + assert.Error(t, pubAgg1.Verify(msg2, agg3)) + assert.Error(t, pubAgg1.Verify(msg1, agg4)) + assert.Error(t, pubAgg3.Verify(msg1, agg1)) + assert.NoError(t, pubAgg1.Verify(msg1, agg5)) + assert.NoError(t, pubAgg4.Verify(msg1, agg1)) +} + +func TestAggregateOnlyOneSignature(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv1 := ts.RandBLSKeyPair() + msg1 := []byte("zarb") + sig1 := prv1.Sign(msg1).(*bls.Signature) + agg1 := bls.SignatureAggregate(sig1) + + assert.True(t, agg1.EqualsTo(sig1)) +} + +func TestAggregateOnlyOnePublicKey(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandBLSKeyPair() + agg1 := bls.PublicKeyAggregate(pub1) + + assert.True(t, agg1.EqualsTo(pub1)) +} + +// TODO: should we check for duplication here? +func TestDuplicatedAggregate(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, prv1 := ts.RandBLSKeyPair() + pub2, prv2 := ts.RandBLSKeyPair() + + msg1 := []byte("zarb") + + sig1 := prv1.Sign(msg1).(*bls.Signature) + sig2 := prv2.Sign(msg1).(*bls.Signature) + + agg1 := bls.SignatureAggregate(sig1, sig2, sig1) + agg2 := bls.SignatureAggregate(sig1, sig2) + assert.False(t, agg1.EqualsTo(agg2)) + + pubs1 := []*bls.PublicKey{pub1, pub2} + pubs2 := []*bls.PublicKey{pub1, pub2, pub1} + pubAgg1 := bls.PublicKeyAggregate(pubs1...) + pubAgg2 := bls.PublicKeyAggregate(pubs2...) + assert.False(t, pubAgg1.EqualsTo(pubAgg2)) +} + +// TestHashToCurve ensures that the hash-to-curve function in kilic/bls12-381 +// works as intended and is compatible with the spec. +// test vectors can be found here: +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#appendix-J.9.1 +func TestHashToCurve(t *testing.T) { + domain := []byte("QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_") + tests := []struct { + msg string + expected string + }{ + { + "", + "052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1" + + "08ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265", + }, + { + "abc", + "03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903" + + "0b9c15f3fe6e5cf4211f346271d7b01c8f3b28be689c8429c85b67af215533311f0b8dfaaa154fa6b88176c229f2885d", + }, + { + "abcdef0123456789", + "11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98" + + "03a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709", + }, + { + "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + + "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488" + + "1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38", + }, + } + + g1 := bls12381.NewG1() + for no, test := range tests { + mappedPoint, _ := g1.HashToCurve([]byte(test.msg), domain) + d, _ := hex.DecodeString(test.expected) + expectedPoint, _ := g1.FromBytes(d) + assert.Equal(t, expectedPoint, mappedPoint, + "test %v: not match", no) + } +} diff --git a/crypto/ed25519/errors.go b/crypto/ed25519/errors.go new file mode 100644 index 000000000..21984ca9c --- /dev/null +++ b/crypto/ed25519/errors.go @@ -0,0 +1 @@ +package ed25519 diff --git a/crypto/ed25519/hdkeychain/errors.go b/crypto/ed25519/hdkeychain/errors.go new file mode 100644 index 000000000..acd944e0b --- /dev/null +++ b/crypto/ed25519/hdkeychain/errors.go @@ -0,0 +1,24 @@ +package hdkeychain + +import ( + "errors" + "fmt" +) + +var ( + // ErrInvalidSeedLen describes an error in which the provided seed or + // seed length is not in the allowed range. + ErrInvalidSeedLen = fmt.Errorf("seed length must be between %d and %d "+ + "bits", MinSeedBytes*8, MaxSeedBytes*8) + + // ErrInvalidKeyData describes an error in which the provided key is + // not valid. + ErrInvalidKeyData = errors.New("key data is invalid") + + // ErrInvalidHRP describes an error in which the HRP is not valid. + ErrInvalidHRP = errors.New("HRP is invalid") + + // ErrNonHardenedPath is returned when a non-hardened derivation path is used, + // which is not supported by ed25519. + ErrNonHardenedPath = errors.New("non-hardened derivation not supported") +) diff --git a/crypto/ed25519/hdkeychain/extendedkey.go b/crypto/ed25519/hdkeychain/extendedkey.go new file mode 100644 index 000000000..02846dbe3 --- /dev/null +++ b/crypto/ed25519/hdkeychain/extendedkey.go @@ -0,0 +1,279 @@ +package hdkeychain + +// References: +// SLIP-0010: Universal private key derivation from master private key +// https://github.com/satoshilabs/slips/blob/master/slip-0010.md + +import ( + "bytes" + "crypto/ed25519" + "crypto/hmac" + "crypto/rand" + "crypto/sha512" + "encoding/binary" + "strings" + + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/util/bech32m" + "github.com/pactus-project/pactus/util/encoding" +) + +const ( + // HardenedKeyStart is the index at which a hardened key starts. + HardenedKeyStart = uint32(0x80000000) // 2^31 + + // MinSeedBytes is the minimum number of bytes allowed for a seed to + // a master node. + MinSeedBytes = 16 // 128 bits + + // MaxSeedBytes is the maximum number of bytes allowed for a seed to + // a master node. + MaxSeedBytes = 64 // 512 bits +) + +// ExtendedKey houses all the information needed to support a hierarchical +// deterministic extended key. +type ExtendedKey struct { + key []byte // This will be the bytes of extended public or private key + chainCode []byte + path []uint32 +} + +// newExtendedKey returns a new instance of an extended key with the given +// fields. No error checking is performed here as it's only intended to be a +// convenience method used to create a populated struct. +func newExtendedKey(key, chainCode []byte, path []uint32) *ExtendedKey { + return &ExtendedKey{ + key: key, + chainCode: chainCode, + path: path, + } +} + +// DerivePath returns a derived child extended key from this master key at the +// given path. +func (k *ExtendedKey) DerivePath(path []uint32) (*ExtendedKey, error) { + ext := k + var err error + for _, index := range path { + ext, err = ext.Derive(index) + if err != nil { + return nil, err + } + } + + return ext, nil +} + +// Derive returns a derived child extended key at the given index. +// +// For ed25519 and curve25519 the private keys are no longer multipliers for the group generator; +// instead the hash of the private key is the multiplier. +// For this reason, our scheme for ed25519 and curve25519 does not support public key derivation and +// uses the produced hashes directly as private keys. +func (k *ExtendedKey) Derive(index uint32) (*ExtendedKey, error) { + isChildHardened := index >= HardenedKeyStart + + if !isChildHardened { + return nil, ErrNonHardenedPath + } + + // Calculate derive Data: + // Data = 0x00 || ser_256(k_par) || ser_32(i) + indexData := make([]byte, 4) + binary.BigEndian.PutUint32(indexData, index) + + data := make([]byte, 0, 37) + data = append(data, 0x00) + data = append(data, k.key...) + data = append(data, indexData...) + + // Take the HMAC-SHA512 of the current key's chain code and the derived + // data: + // I = HMAC-SHA512(Key = chainCode, Data = data) + hmac512 := hmac.New(sha512.New, k.chainCode) + _, _ = hmac512.Write(data) + ilr := hmac512.Sum(nil) + + // Split I into two 32-byte sequences, IL and IR. + // The returned chain code ci is IR. + // The returned child key ki is IL. + childChainCode := ilr[32:] + childKey := ilr[:32] + + newPath := make([]uint32, 0, len(k.path)+1) + newPath = append(newPath, k.path...) + newPath = append(newPath, index) + + return newExtendedKey(childKey, childChainCode, newPath), nil +} + +// Path returns the path of derived key. +// +// Path values are always between 2^31 and 2^32-1 as they are hardened keys. +func (k *ExtendedKey) Path() []uint32 { + return k.path +} + +// RawPrivateKey returns the raw bytes of the private key. +func (k *ExtendedKey) RawPrivateKey() []byte { + return k.key +} + +// RawPublicKey returns the raw bytes of the public key. +func (k *ExtendedKey) RawPublicKey() []byte { + pub := ed25519.NewKeyFromSeed(k.key).Public() + + return pub.(ed25519.PublicKey)[:] +} + +// String returns the extended key as a bech32-encoded string. +func (k *ExtendedKey) String() string { + // + // The serialized format is structured as follows: + // +-------+---------+------------+----------+------------+----------+ + // | Depth | Path | Chain code | Reserved | Key length | Key data | + // +-------+---------+------------+----------+------------+----------+ + // | 1 | depth*4 | 32 | 1 | 1 | 32 | + // +-------+---------+------------+----------+------------+----------+ + // + // Description: + // - Depth: 1 byte representing the depth of derivation path. + // - Path: serialized BIP-32 path; each entry is encoded as 32-bit unsigned integer, least significant byte first + // - Chain code: 32 bytes chain code + // - Reserved: 1 byte reserved and should set to 0. + // - Key length: 1 byte representing the length of the key data that is 32. + // - Key data: The key data that is 32 bytes. + // + + w := bytes.NewBuffer(make([]byte, 0)) + err := encoding.WriteElement(w, byte(len(k.path))) + if err != nil { + return err.Error() + } + + for _, p := range k.path { + err := encoding.WriteElement(w, p) + if err != nil { + return err.Error() + } + } + err = encoding.WriteVarBytes(w, k.chainCode) + if err != nil { + return err.Error() + } + + err = encoding.WriteElement(w, uint8(0)) + if err != nil { + return err.Error() + } + + err = encoding.WriteVarBytes(w, k.key) + if err != nil { + return err.Error() + } + + str, err := bech32m.EncodeFromBase256WithType(crypto.XPrivateKeyHRP, crypto.SignatureTypeEd25519, w.Bytes()) + if err != nil { + return err.Error() + } + + str = strings.ToUpper(str) + + return str +} + +// NewKeyFromString returns a new extended key instance from a bech32-encoded string. +func NewKeyFromString(str string) (*ExtendedKey, error) { + hrp, typ, data, err := bech32m.DecodeToBase256WithTypeNoLimit(strings.ToLower(str)) + if err != nil { + return nil, err + } + + if typ != crypto.SignatureTypeEd25519 { + return nil, ErrInvalidKeyData + } + + if hrp != crypto.XPrivateKeyHRP { + return nil, ErrInvalidHRP + } + + r := bytes.NewReader(data) + depth := uint8(0) + err = encoding.ReadElement(r, &depth) + if err != nil { + return nil, err + } + + path := make([]uint32, depth) + for i := byte(0); i < depth; i++ { + err := encoding.ReadElement(r, &path[i]) + if err != nil { + return nil, err + } + } + + chainCode, err := encoding.ReadVarBytes(r) + if err != nil { + return nil, err + } + + var res uint8 + err = encoding.ReadElement(r, &res) + if err != nil { + return nil, err + } + + key, err := encoding.ReadVarBytes(r) + if err != nil { + return nil, err + } + + return newExtendedKey(key, chainCode, path), nil +} + +// NewMaster creates a new master node for use in creating a hierarchical +// deterministic key chain. The seed must be between 128 and 512 bits and +// should be generated by a cryptographically secure random generation source. +func NewMaster(seed []byte) (*ExtendedKey, error) { + // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. + if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes { + return nil, ErrInvalidSeedLen + } + + // First take the HMAC-SHA512 of the master key and the seed data: + // I = HMAC-SHA512(Key = Curve, Data = Seed) + curve := []byte("ed25519 seed") + hmac512 := hmac.New(sha512.New, curve) + _, _ = hmac512.Write(seed) + lr := hmac512.Sum(nil) + + // Split "I" into two 32-byte sequences Il and Ir where: + // Il = master key + // Ir = master chain code + masterChainCode := lr[32:] + masterKey := lr[:32] + + return newExtendedKey(masterKey, masterChainCode, []uint32{}), nil +} + +// GenerateSeed returns a cryptographically secure random seed that can be used +// as the input for the NewMaster function to generate a new master node. +// +// The length is in bytes and it must be between 16 and 64 (128 to 512 bits). +// The recommended length is 32 (256 bits) as defined by the RecommendedSeedLen +// constant. +func GenerateSeed(length uint8) ([]byte, error) { + // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. + if length < MinSeedBytes || length > MaxSeedBytes { + return nil, ErrInvalidSeedLen + } + + buf := make([]byte, length) + _, err := rand.Read(buf) + if err != nil { + return nil, err + } + + return buf, nil +} diff --git a/crypto/ed25519/hdkeychain/extendedkey_test.go b/crypto/ed25519/hdkeychain/extendedkey_test.go new file mode 100644 index 000000000..bb7e87073 --- /dev/null +++ b/crypto/ed25519/hdkeychain/extendedkey_test.go @@ -0,0 +1,314 @@ +package hdkeychain + +import ( + "encoding/hex" + "io" + "testing" + + "github.com/pactus-project/pactus/util/bech32m" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestNonHardenedDerivation tests deriving a new key in non-hardened mode. +// It should return an error. +func TestNonHardenedDerivation(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + testSeed := ts.RandBytes(32) + path := []uint32{ + ts.RandUint32(HardenedKeyStart), + } + + masterKey, _ := NewMaster(testSeed) + _, err := masterKey.DerivePath(path) + assert.ErrorIs(t, err, ErrNonHardenedPath) +} + +// TestHardenedDerivation tests derive key in hardened mode. +func TestHardenedDerivation(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + testSeed := ts.RandBytes(32) + path := []uint32{ + ts.RandUint32(HardenedKeyStart) + HardenedKeyStart, + } + + masterKey, err := NewMaster(testSeed) + require.NoError(t, err) + + extKey, err := masterKey.DerivePath(path) + require.NoError(t, err) + + assert.Equal(t, path, extKey.Path()) +} + +// TestDerivation verifies the derivation of new keys in hardened mode. +// The test cases are based on the SLIP-0010 standard. +func TestDerivation(t *testing.T) { + testSeed, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f") + h := HardenedKeyStart + tests := []struct { + name string + path []uint32 + wantPrv string + wantPub string + }{ + { + name: "derivation path: m", + path: []uint32{}, + wantPrv: "2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7", + wantPub: "a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed", + }, + { + name: "derivation path: m/0H", + path: []uint32{h}, + wantPrv: "68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3", + wantPub: "8c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c", + }, + { + name: "derivation path: m/0H/1H", + path: []uint32{h, 1 + h}, + wantPrv: "b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2", + wantPub: "1932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187", + }, + { + name: "derivation path: m/0H/1H/2H", + path: []uint32{h, 1 + h, 2 + h}, + wantPrv: "92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9", + wantPub: "ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1", + }, + { + name: "derivation path: m/0H/1H/2H/2H", + path: []uint32{h, 1 + h, 2 + h, 2 + h}, + wantPrv: "30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662", + wantPub: "8abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c", + }, + { + name: "derivation path: m/0H/1H/2H/2H/1000000000H", + path: []uint32{h, 1 + h, 2 + h, 2 + h, 1000000000 + h}, + wantPrv: "8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793", + wantPub: "3c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a", + }, + } + + masterKey, _ := NewMaster(testSeed) + for i, test := range tests { + extKey, err := masterKey.DerivePath(test.path) + require.NoError(t, err) + + privKey := extKey.RawPrivateKey() + require.Equal(t, test.wantPrv, hex.EncodeToString(privKey), + "mismatched serialized private key for test #%v", i+1) + + pubKey := extKey.RawPublicKey() + require.Equal(t, test.wantPub, hex.EncodeToString(pubKey), + "mismatched serialized public key for test #%v", i+1) + + require.Equal(t, test.path, extKey.Path()) + } +} + +// TestGenerateSeed ensures the GenerateSeed function works as intended. +func TestGenerateSeed(t *testing.T) { + tests := []struct { + name string + length uint8 + err error + }{ + // Test various valid lengths. + {name: "16 bytes", length: 16}, + {name: "17 bytes", length: 17}, + {name: "20 bytes", length: 20}, + {name: "32 bytes", length: 32}, + {name: "64 bytes", length: 64}, + + // Test invalid lengths. + {name: "15 bytes", length: 15, err: ErrInvalidSeedLen}, + {name: "65 bytes", length: 65, err: ErrInvalidSeedLen}, + } + + for i, test := range tests { + seed, err := GenerateSeed(test.length) + assert.ErrorIs(t, err, test.err) + + if test.err == nil { + assert.Len(t, seed, int(test.length), + "GenerateSeed #%d (%s): length mismatch -- got %d, want %d", + i+1, test.name, len(seed), test.length) + } + } +} + +// TestNewMaster ensures the NewMaster function works as intended. +func TestNewMaster(t *testing.T) { + tests := []struct { + name string + seed string + key string + err error + }{ + // Test various valid seeds. + { + name: "16 bytes", + seed: "000102030405060708090a0b0c0d0e0f", + key: "2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7", + }, + { + name: "32 bytes", + seed: "3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678", + key: "4b36bc63a15797f4d506074f36f2f3904bc0f10179b5ab91183c167e9c2dcf0e", + }, + { + name: "64 bytes", + seed: "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784" + + "817e7b7875726f6c696663605d5a5754514e4b484542", + key: "171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012", + }, + + // Test invalid seeds. + { + name: "empty seed", + seed: "", + err: ErrInvalidSeedLen, + }, + { + name: "15 bytes", + seed: "000000000000000000000000000000", + err: ErrInvalidSeedLen, + }, + { + name: "65 bytes", + seed: "000000000000000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000", + err: ErrInvalidSeedLen, + }, + } + + for i, test := range tests { + seed, _ := hex.DecodeString(test.seed) + extKey, err := NewMaster(seed) + assert.ErrorIs(t, err, test.err) + + if test.err == nil { + privKey := extKey.RawPrivateKey() + assert.Equal(t, test.key, hex.EncodeToString(privKey), + "NewMaster #%d (%s): key mismatch -- got %x, want %s", + i+1, test.name, privKey, test.key) + } + } +} + +// TestKeyToString ensures the String function works as intended. +// +//nolint:lll // long extended keys +func TestKeyToString(t *testing.T) { + testSeed, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f") + h := HardenedKeyStart + tests := []struct { + name string + path []uint32 + wantXPriv string + }{ + { + name: "derivation path: m", + path: []uint32{}, + wantXPriv: "XSECRET1RQQSFQPR2J0098Q989D0Y2QG8FPT86H4Q9WLK2GHE08S9CRVD3J5LL7CQYQ45HEL3NM38H0ESCENMVSK47J4XNLGKNPE03LPST8QGAWHZAVV7WQ3TTQ3", + }, + { + name: "derivation path: m/0H", + path: []uint32{h}, + wantXPriv: "XSECRET1RQYQQQQYQYZ94N2S38Q9KYN5P2PAZ0LKA5K075MGTW7D80ZGC5T7NTY8PD6WXJQPQDRS0U3KLKELRDRR4X7DVA3V3MTGEMU7DUFHX8WF63ECY78DDU73SSP8VGW", + }, + { + name: "derivation path: m/0H/1H", + path: []uint32{h, 1 + h}, + wantXPriv: "XSECRET1RQGQQQQYQQYQQPQPQ5VSYYHMH6X6UY5Z6DVDJWWPTXUMGAEJQUD2HCV25Z6QPYS649U2QQG936ZADGP9LXHD8SKNYEGDV2JEXZUS36FMHD9HML7HJPRM5DT5Y7GG0AYKR", + }, + { + name: "derivation path: m/0H/1H/2H", + path: []uint32{h, 1 + h, 2 + h}, + wantXPriv: "XSECRET1RQVQQQQYQQYQQPQQZQQQGQGPWDXFFUQ944VJS7JWRLVWP9UJJME876TQAHZPCWZ22P7XYE8XDDSQZPY49KG7QHZ5EUD7S0HELHXTXJ9L46PHQ9HDAJZW8UXZRW9RRA87FNLUP3Y", + }, + { + name: "derivation path: m/0H/1H/2H/2H", + path: []uint32{h, 1 + h, 2 + h, 2 + h}, + wantXPriv: "XSECRET1RQSQQQQYQQYQQPQQZQQQGQQSQQZQZPRMDSLUN6AGWPM7VMGQH6E32RVC6YEHY5M6EJWC47HQLQLM5M4WVQQSRP5WU0E0UQNP3YXDTYK384CQT2RM06ENZ9AHFEYFJ20T9Z8G7VCSW77AAC", + }, + { + name: "derivation path: m/0H/1H/2H/2H/1000000000H", + path: []uint32{h, 1 + h, 2 + h, 2 + h, 1000000000 + h}, + wantXPriv: "XSECRET1RQ5QQQQYQQYQQPQQZQQQGQQSQQZQQPJ56HVSXS7YEYWSV4SKDTG53W2J8TL57P7C5E44DKKKE3GL6WQENU7H6YVQQYZ8EF5U54R5066CMCTELF86UGL3C22QATST7V5EYKRMZFQLR06REXGPVGYE", + }, + } + + masterKey, _ := NewMaster(testSeed) + for i, test := range tests { + extKey, _ := masterKey.DerivePath(test.path) + require.Equal(t, test.wantXPriv, extKey.String(), "test %d failed", i) + + recoveredExtKey, err := NewKeyFromString(test.wantXPriv) + require.NoError(t, err) + + require.Equal(t, extKey, recoveredExtKey) + require.Equal(t, test.path, recoveredExtKey.path) + } +} + +// TestInvalidString checks errors corresponding to the invalid strings +// +//nolint:lll // long extended private keys +func TestInvalidString(t *testing.T) { + tests := []struct { + desc string + str string + expectedError error + }{ + { + desc: "invalid checksum", + str: "XSECRET1RQGQQQQYQQYQQPQPQ5VSYYHMH6X6UY5Z6DVDJWWPTXUMGAEJQUD2HCV25Z6QPYS649U2QQG936ZADGP9LXHD8SKNYEGDV2JEXZUS36FMHD9HML7HJPRM5DT5Y7GG0AYRK", + expectedError: bech32m.InvalidChecksumError{Expected: "g0aykr", Actual: "g0ayrk"}, + }, + { + desc: "no depth", + str: "XSECRET1RFK28CY", + expectedError: io.EOF, + }, + { + desc: "wrong path", + str: "XSECRET1RQGQQQQYQ6EJ6DE", + expectedError: io.EOF, + }, + { + desc: "no chain code", + str: "XSECRET1RQGQQQQYQQYQQPQQ98TS98", + expectedError: io.EOF, + }, + { + desc: "no reserved", + str: "XSECRET1RQGQQQQYQQYQQPQPQ5VSYYHMH6X6UY5Z6DVDJWWPTXUMGAEJQUD2HCV25Z6QPYS649U2Q8GUZZJ", + expectedError: io.EOF, + }, + { + desc: "no key", + str: "XSECRET1RQGQQQQYQQYQQPQPQ5VSYYHMH6X6UY5Z6DVDJWWPTXUMGAEJQUD2HCV25Z6QPYS649U2QQ85HSJA", + expectedError: io.EOF, + }, + { + desc: "invalid type", + str: "XSECRET1YQGQQQQYQQYQQPQPQ5VSYYHMH6X6UY5Z6DVDJWWPTXUMGAEJQUD2HCV25Z6QPYS649U2QQG936ZADGP9LXHD8SKNYEGDV2JEXZUS36FMHD9HML7HJPRM5DT5Y7GTKSQQT", + expectedError: ErrInvalidKeyData, + }, + { + desc: "invalid hrp", + str: "SECRET1RQGQQQQYQQYQQPQPQ5VSYYHMH6X6UY5Z6DVDJWWPTXUMGAEJQUD2HCV25Z6QPYS649U2QQG936ZADGP9LXHD8SKNYEGDV2JEXZUS36FMHD9HML7HJPRM5DT5Y7GYQ7VAT", + expectedError: ErrInvalidHRP, + }, + } + + for i, test := range tests { + _, err := NewKeyFromString(test.str) + assert.ErrorIs(t, err, test.expectedError, "test %d error is not matched", i) + } +} diff --git a/crypto/ed25519/private_key.go b/crypto/ed25519/private_key.go new file mode 100644 index 000000000..0a0820dde --- /dev/null +++ b/crypto/ed25519/private_key.go @@ -0,0 +1,108 @@ +package ed25519 + +import ( + "crypto/ed25519" + "strings" + + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/util/bech32m" + "github.com/pactus-project/pactus/util/errors" +) + +var _ crypto.PrivateKey = &PrivateKey{} + +const PrivateKeySize = 32 + +type PrivateKey struct { + inner ed25519.PrivateKey +} + +// PrivateKeyFromString decodes the input string and returns the PrivateKey +// if the string is a valid bech32m encoding of a BLS public key. +func PrivateKeyFromString(text string) (*PrivateKey, error) { + // Decode the bech32m encoded private key. + hrp, typ, data, err := bech32m.DecodeToBase256WithTypeNoLimit(text) + if err != nil { + return nil, err + } + + // Check if hrp is valid + if hrp != crypto.PrivateKeyHRP { + return nil, crypto.InvalidHRPError(hrp) + } + + if typ != crypto.SignatureTypeEd25519 { + return nil, errors.Errorf(errors.ErrInvalidPrivateKey, + "invalid private key type: %v", typ) + } + + return PrivateKeyFromBytes(data) +} + +func KeyGen(seed []byte) (*PrivateKey, error) { + prv := ed25519.NewKeyFromSeed(seed) + + return PrivateKeyFromBytes(prv) +} + +// PrivateKeyFromBytes constructs a ED25519 private key from the raw bytes. +func PrivateKeyFromBytes(data []byte) (*PrivateKey, error) { + if len(data) != PrivateKeySize { + return nil, errors.Errorf(errors.ErrInvalidPrivateKey, + "private key should be %d bytes, but it is %v bytes", PrivateKeySize, len(data)) + } + inner := ed25519.NewKeyFromSeed(data) + + return &PrivateKey{inner}, nil +} + +// String returns a human-readable string for the ED25519 private key. +func (prv *PrivateKey) String() string { + str, _ := bech32m.EncodeFromBase256WithType( + crypto.PrivateKeyHRP, + crypto.SignatureTypeEd25519, + prv.Bytes()) + + return strings.ToUpper(str) +} + +// Bytes return the raw bytes of the private key. +func (prv *PrivateKey) Bytes() []byte { + return prv.inner[:PrivateKeySize] +} + +// Sign calculates the signature from the private key and given message. +// It's defined in section 2.6 of the spec: CoreSign. +func (prv *PrivateKey) Sign(msg []byte) crypto.Signature { + return prv.SignNative(msg) +} + +func (prv *PrivateKey) SignNative(msg []byte) *Signature { + sig := ed25519.Sign(prv.inner, msg) + + return &Signature{ + data: sig, + } +} + +func (prv *PrivateKey) PublicKeyNative() *PublicKey { + pub := prv.inner.Public() + + // TODO: fix me, should get from scalar multiplication. + return &PublicKey{ + inner: pub.(ed25519.PublicKey), + } +} + +func (prv *PrivateKey) PublicKey() crypto.PublicKey { + return prv.PublicKeyNative() +} + +func (prv *PrivateKey) EqualsTo(x crypto.PrivateKey) bool { + xEd25519, ok := x.(*PrivateKey) + if !ok { + return false + } + + return prv.inner.Equal(xEd25519.inner) +} diff --git a/crypto/ed25519/private_key_test.go b/crypto/ed25519/private_key_test.go new file mode 100644 index 000000000..447650688 --- /dev/null +++ b/crypto/ed25519/private_key_test.go @@ -0,0 +1,105 @@ +package ed25519_test + +import ( + "encoding/hex" + "fmt" + "strings" + "testing" + + "github.com/pactus-project/pactus/crypto/ed25519" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" +) + +func TestPrivateKeyEqualsTo(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv1 := ts.RandED25519KeyPair() + _, prv2 := ts.RandED25519KeyPair() + + fmt.Println(prv1.String()) + + assert.True(t, prv1.EqualsTo(prv1)) + assert.False(t, prv1.EqualsTo(prv2)) + assert.Equal(t, prv1, prv1) + assert.NotEqual(t, prv1, prv2) +} + +func TestPrivateKeyFromString(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + result []byte + }{ + { + "invalid separator index -1", + "XXXXXXR2SYCC5TDQKMJ73J64J8GJTMTKREEQNQAS0M5SLZ9LVJV7Y940NVZQD9JUS" + + "GV2N44C9H5PVGRXARNGZ7QF3PSKH7805E5SZXPE7ZHHAGX0NFQR", + false, nil, + }, + { + "invalid checksum (expected s9c56g got czlgh0)", + "SECRET1RAC7048K666DCCYG7FJW68ZE2G6P32UAPLRLWDV3RTAR4PWZUX2CDSFAL55VM" + + "YS06CY35LA72AWZN5DY5NZA078S4S4K654UFJ0YCCZLGH0", + false, nil, + }, + { + "invalid bech32 string length 0", + "", + false, nil, + }, + { + "invalid character not part of charset: 105", + "SECRET1IOIOOI", + false, nil, + }, + { + "invalid bech32 string length 0", + "SECRET1HPZZU9", + false, nil, + }, + { + "", + "SECRET1RJ6STNTA7Y3P2QLQF8A6QCX05F2H5TFNE5RSH066KZME4WVFXKE7QW097LG", + true, + []byte{ + 0x96, 0xa0, 0xb9, 0xaf, 0xbe, 0x24, 0x42, 0xa0, 0x7c, 0x9, 0x3f, 0x74, 0xc, 0x19, 0xf4, + 0x4a, 0xaf, 0x45, 0xa6, 0x79, 0xa0, 0xe1, 0x77, 0xeb, 0x56, 0x16, 0xf3, 0x57, 0x31, 0x26, + 0xb6, 0x7c, + }, + }, + } + + for no, test := range tests { + prv, err := ed25519.PrivateKeyFromString(test.encoded) + if test.valid { + assert.NoError(t, err, "test %v: unexpected error", no) + assert.Equal(t, test.result, prv.Bytes(), "test %v: invalid bytes", no) + assert.Equal(t, strings.ToUpper(test.encoded), prv.String(), "test %v: invalid encoded", no) + } else { + assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) + } + } +} + +// TestKeyGen ensures the KeyGen function works as intended. +func TestKeyGen(t *testing.T) { + tests := []struct { + seed []byte + sk string + }{} + + for i, test := range tests { + prv, err := ed25519.KeyGen(test.seed) + if test.sk == "Err" { + assert.Error(t, err, + "test '%v' failed. no error", i) + } else { + assert.NoError(t, err, + "test'%v' failed. has error", i) + assert.Equal(t, test.sk, hex.EncodeToString(prv.Bytes()), + "test '%v' failed. not equal", i) + } + } +} diff --git a/crypto/ed25519/public_key.go b/crypto/ed25519/public_key.go new file mode 100644 index 000000000..24f0ae2c4 --- /dev/null +++ b/crypto/ed25519/public_key.go @@ -0,0 +1,146 @@ +package ed25519 + +import ( + "bytes" + "crypto/ed25519" + "io" + + cbor "github.com/fxamacker/cbor/v2" + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/crypto/hash" + "github.com/pactus-project/pactus/util/bech32m" + "github.com/pactus-project/pactus/util/encoding" + "github.com/pactus-project/pactus/util/errors" +) + +var _ crypto.PublicKey = &PublicKey{} + +const PublicKeySize = 32 + +type PublicKey struct { + inner ed25519.PublicKey +} + +// PublicKeyFromString decodes the input string and returns the PublicKey +// if the string is a valid bech32m encoding of a BLS public key. +func PublicKeyFromString(text string) (*PublicKey, error) { + // Decode the bech32m encoded public key. + hrp, typ, data, err := bech32m.DecodeToBase256WithTypeNoLimit(text) + if err != nil { + return nil, err + } + + // Check if hrp is valid + if hrp != crypto.PublicKeyHRP { + return nil, crypto.InvalidHRPError(hrp) + } + + if typ != crypto.SignatureTypeEd25519 { + return nil, errors.Errorf(errors.ErrInvalidPublicKey, "invalid public key type: %v", typ) + } + + return PublicKeyFromBytes(data) +} + +// PublicKeyFromBytes constructs a BLS public key from the raw bytes. +func PublicKeyFromBytes(data []byte) (*PublicKey, error) { + if len(data) != PublicKeySize { + return nil, errors.Errorf(errors.ErrInvalidPublicKey, + "public key should be %d bytes, but it is %v bytes", PublicKeySize, len(data)) + } + + return &PublicKey{data}, nil +} + +// Bytes returns the raw byte representation of the public key. +func (pub *PublicKey) Bytes() []byte { + return pub.inner[:PublicKeySize] +} + +// String returns a human-readable string for the BLS public key. +func (pub *PublicKey) String() string { + str, _ := bech32m.EncodeFromBase256WithType( + crypto.PublicKeyHRP, + crypto.SignatureTypeBLS, + pub.Bytes()) + + return str +} + +// MarshalCBOR encodes the public key into CBOR format. +func (pub *PublicKey) MarshalCBOR() ([]byte, error) { + return cbor.Marshal(pub.Bytes()) +} + +// UnmarshalCBOR decodes the public key from CBOR format. +func (pub *PublicKey) UnmarshalCBOR(bs []byte) error { + var data []byte + if err := cbor.Unmarshal(bs, &data); err != nil { + return err + } + + return pub.Decode(bytes.NewReader(data)) +} + +// Encode writes the raw bytes of the public key to the provided writer. +func (pub *PublicKey) Encode(w io.Writer) error { + return encoding.WriteElements(w, pub.Bytes()) +} + +// Decode reads the raw bytes of the public key from the provided reader and initializes the public key. +func (pub *PublicKey) Decode(r io.Reader) error { + data := make([]byte, PublicKeySize) + err := encoding.ReadElements(r, data) + if err != nil { + return err + } + + p, _ := PublicKeyFromBytes(data) + *pub = *p + + return nil +} + +// Verify checks that a signature is valid for the given message and public key. +// It's defined in section 2.6 of the spec: CoreVerify. +func (pub *PublicKey) Verify(msg []byte, sig crypto.Signature) error { + if sig == nil { + return errors.Error(errors.ErrInvalidSignature) + } + + if !ed25519.Verify(pub.inner, msg, sig.Bytes()) { + return crypto.ErrInvalidSignature + } + + return nil +} + +// EqualsTo checks if the current public key is equal to another public key. +func (pub *PublicKey) EqualsTo(x crypto.PublicKey) bool { + xEd25519, ok := x.(*PublicKey) + if !ok { + return false + } + + return pub.inner.Equal(xEd25519.inner) +} + +// AccountAddress returns the account address derived from the public key. +func (pub *PublicKey) AccountAddress() crypto.Address { + data := hash.Hash160(hash.Hash256(pub.Bytes())) + addr := crypto.NewAddress(crypto.AddressTypeBLSAccount, data) + + return addr +} + +// VerifyAddress checks if the provided address matches the derived address from the public key. +func (pub *PublicKey) VerifyAddress(addr crypto.Address) error { + if addr != pub.AccountAddress() { + return crypto.AddressMismatchError{ + Expected: pub.AccountAddress(), + Got: addr, + } + } + + return nil +} diff --git a/crypto/ed25519/public_key_test.go b/crypto/ed25519/public_key_test.go new file mode 100644 index 000000000..2be99a142 --- /dev/null +++ b/crypto/ed25519/public_key_test.go @@ -0,0 +1,233 @@ +package ed25519_test + +import ( + "encoding/hex" + "strings" + "testing" + + cbor "github.com/fxamacker/cbor/v2" + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/util" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPublicKeyCBORMarshaling(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandBLSKeyPair() + pub2 := new(bls.PublicKey) + + bs, err := pub1.MarshalCBOR() + assert.NoError(t, err) + assert.NoError(t, pub2.UnmarshalCBOR(bs)) + assert.True(t, pub1.EqualsTo(pub2)) + + assert.Error(t, pub2.UnmarshalCBOR([]byte("abcd"))) + + inv, _ := hex.DecodeString(strings.Repeat("ff", bls.PublicKeySize)) + data, _ := cbor.Marshal(inv) + assert.NoError(t, pub2.UnmarshalCBOR(data)) + + _, err = pub2.PointG2() + assert.Error(t, err) +} + +func TestPublicKeyEqualsTo(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandBLSKeyPair() + pub2, _ := ts.RandBLSKeyPair() + + assert.True(t, pub1.EqualsTo(pub1)) + assert.False(t, pub1.EqualsTo(pub2)) + assert.Equal(t, pub1, pub1) + assert.NotEqual(t, pub1, pub2) +} + +func TestPublicKeyEncoding(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub, _ := ts.RandBLSKeyPair() + w1 := util.NewFixedWriter(20) + assert.Error(t, pub.Encode(w1)) + + w2 := util.NewFixedWriter(bls.PublicKeySize) + assert.NoError(t, pub.Encode(w2)) + + r1 := util.NewFixedReader(20, w2.Bytes()) + assert.Error(t, pub.Decode(r1)) + + r2 := util.NewFixedReader(bls.PublicKeySize, w2.Bytes()) + assert.NoError(t, pub.Decode(r2)) +} + +func TestPublicKeyVerifyAddress(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandBLSKeyPair() + pub2, _ := ts.RandBLSKeyPair() + + err := pub1.VerifyAddress(pub1.AccountAddress()) + assert.NoError(t, err) + err = pub1.VerifyAddress(pub1.ValidatorAddress()) + assert.NoError(t, err) + + err = pub1.VerifyAddress(pub2.AccountAddress()) + assert.Equal(t, crypto.AddressMismatchError{ + Expected: pub1.AccountAddress(), + Got: pub2.AccountAddress(), + }, err) + + err = pub1.VerifyAddress(pub2.ValidatorAddress()) + assert.Equal(t, crypto.AddressMismatchError{ + Expected: pub1.ValidatorAddress(), + Got: pub2.ValidatorAddress(), + }, err) +} + +func TestNilPublicKey(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub := &bls.PublicKey{} + randSig := ts.RandBLSSignature() + assert.Error(t, pub.VerifyAddress(ts.RandAccAddress())) + assert.Error(t, pub.VerifyAddress(ts.RandValAddress())) + assert.Error(t, pub.Verify(nil, nil)) + assert.Error(t, pub.Verify(nil, &bls.Signature{})) + assert.Error(t, pub.Verify(nil, randSig)) +} + +func TestNilSignature(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub, _ := ts.RandBLSKeyPair() + assert.Error(t, pub.Verify(nil, nil)) + assert.Error(t, pub.Verify(nil, &bls.Signature{})) +} + +func TestPublicKeyBytes(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + result []byte + }{ + { + "invalid separator index -1", + "not_proper_encoded", + false, nil, + }, + { + "invalid bech32 string length 0", + "", + false, nil, + }, + { + "invalid character not part of charset: 105", + "public1ioiooi", + false, nil, + }, + { + "invalid bech32 string length 0", + "public134jkgz", + false, nil, + }, + { + "invalid HRP: xxx", + "xxx1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjrvqc" + + "vf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5evslaq", + false, nil, + }, + { + "invalid checksum (expected jhx47a got jhx470)", + "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + + "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx470", + false, nil, + }, + { + "public key should be 96 bytes, but it is 95 bytes", + "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + + "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg73y98kl", + false, nil, + }, + { + "invalid public key type: 2", + "public1z372l5frmm5e7cn7ewfjdkx5t7y62kztqr82rtatat70cl8p8ng3rdzr02mzpwcfl6s2v26kry6mwg" + + "xpqy92ywx9wtff80mc9p3kr4cmhgekj048gavx2zdh78tsnh7eg5jzdw6s3et6c0dqyp22vslcgkukxh4l4", + false, nil, + }, + { + "", + "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + + "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a", + true, + []byte{ + 0xaf, 0x0f, 0x74, 0x91, 0x7f, 0x50, 0x65, 0xaf, 0x94, 0x72, 0x7a, 0xe9, 0x54, 0x1b, 0x0d, 0xdc, + 0xfb, 0x5b, 0x82, 0x8a, 0x9e, 0x01, 0x6b, 0x02, 0x49, 0x8f, 0x47, 0x7e, 0xd3, 0x7f, 0xb4, 0x4d, 0x5d, + 0x88, 0x24, 0x95, 0xaf, 0xb6, 0xfd, 0x4f, 0x97, 0x73, 0xe4, 0xea, 0x9d, 0xee, 0xe4, 0x36, 0x03, 0x0c, + 0x4d, 0x61, 0xc6, 0xe3, 0xa1, 0x15, 0x15, 0x85, 0xe1, 0xd8, 0x38, 0xca, 0xe1, 0x44, 0x4a, 0x43, 0x8d, + 0x08, 0x9c, 0xe7, 0x7e, 0x10, 0xc4, 0x92, 0xa5, 0x5f, 0x69, 0x08, 0x12, 0x5c, 0x5b, 0xe9, 0xb2, 0x36, + 0xa2, 0x46, 0xe4, 0x08, 0x2d, 0x08, 0xde, 0x56, 0x4e, 0x11, 0x1e, 0x65, + }, + }, + } + + for no, test := range tests { + pub, err := bls.PublicKeyFromString(test.encoded) + if test.valid { + assert.NoError(t, err, "test %v: unexpected error", no) + assert.Equal(t, test.result, pub.Bytes(), "test %v: invalid bytes", no) + assert.Equal(t, test.encoded, pub.String(), "test %v: invalid encoded", no) + } else { + assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) + } + } +} + +func TestPointG2(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + }{ + { + "compression flag must be set", + "public1pqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + + "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqjzu9w8", + false, + }, + { + "input string must be zero when infinity flag is set", + "public1pllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll" + + "llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllluhpuzyf", + false, + }, + { + "public key is zero", + "public1pcqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + + "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqglnhh9", + false, + }, + { + "", + "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + + "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a", + true, + }, + } + + for no, test := range tests { + pub, err := bls.PublicKeyFromString(test.encoded) + require.NoError(t, err) + + _, err = pub.PointG2() + if test.valid { + assert.NoError(t, err, "test %v: unexpected error", no) + } else { + assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) + } + } +} diff --git a/crypto/ed25519/signature.go b/crypto/ed25519/signature.go new file mode 100644 index 000000000..98c08d2d6 --- /dev/null +++ b/crypto/ed25519/signature.go @@ -0,0 +1,91 @@ +package ed25519 + +import ( + "bytes" + "crypto/subtle" + "encoding/hex" + "io" + + cbor "github.com/fxamacker/cbor/v2" + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/util/encoding" + "github.com/pactus-project/pactus/util/errors" +) + +var _ crypto.Signature = &Signature{} + +const SignatureSize = 64 + +type Signature struct { + data []byte +} + +// SignatureFromString decodes the input string and returns the Signature +// if the string is a valid hexadecimal encoding of a BLS signature. +func SignatureFromString(text string) (*Signature, error) { + data, err := hex.DecodeString(text) + if err != nil { + return nil, err + } + + return SignatureFromBytes(data) +} + +// SignatureFromBytes constructs a BLS signature from the raw bytes. +func SignatureFromBytes(data []byte) (*Signature, error) { + if len(data) != SignatureSize { + return nil, errors.Errorf(errors.ErrInvalidSignature, + "signature should be %d bytes, but it is %v bytes", SignatureSize, len(data)) + } + + return &Signature{data: data}, nil +} + +// Bytes returns the raw byte representation of the signature. +func (sig *Signature) Bytes() []byte { + return sig.data[:SignatureSize] +} + +// String returns the hex-encoded string representation of the signature. +func (sig *Signature) String() string { + return hex.EncodeToString(sig.Bytes()) +} + +// MarshalCBOR encodes the signature into CBOR format. +func (sig *Signature) MarshalCBOR() ([]byte, error) { + return cbor.Marshal(sig.Bytes()) +} + +// UnmarshalCBOR decodes the signature from CBOR format. +func (sig *Signature) UnmarshalCBOR(bs []byte) error { + var data []byte + if err := cbor.Unmarshal(bs, &data); err != nil { + return err + } + + return sig.Decode(bytes.NewReader(data)) +} + +// Encode writes the raw bytes of the signature to the provided writer. +func (sig *Signature) Encode(w io.Writer) error { + return encoding.WriteElements(w, sig.Bytes()) +} + +// Decode reads the raw bytes of the signature from the provided reader and initializes the signature. +func (sig *Signature) Decode(r io.Reader) error { + data := make([]byte, SignatureSize) + err := encoding.ReadElements(r, data) + if err != nil { + return err + } + + s, _ := SignatureFromBytes(data) + *sig = *s + + return nil +} + +// EqualsTo checks if the current signature is equal to another signature. +func (sig *Signature) EqualsTo(right crypto.Signature) bool { + return subtle.ConstantTimeCompare(sig.data, right.(*Signature).data) == 1 +} diff --git a/crypto/ed25519/signature_test.go b/crypto/ed25519/signature_test.go new file mode 100644 index 000000000..78bc94803 --- /dev/null +++ b/crypto/ed25519/signature_test.go @@ -0,0 +1,178 @@ +package ed25519_test + +import ( + "encoding/hex" + "strings" + "testing" + + cbor "github.com/fxamacker/cbor/v2" + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/util" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSignatureCBORMarshaling(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv := ts.RandBLSKeyPair() + sig1 := prv.Sign(ts.RandBytes(16)) + sig2 := new(bls.Signature) + + bs, err := sig1.MarshalCBOR() + assert.NoError(t, err) + assert.NoError(t, sig2.UnmarshalCBOR(bs)) + assert.True(t, sig1.EqualsTo(sig2)) + + assert.Error(t, sig2.UnmarshalCBOR([]byte("abcd"))) + + inv, _ := hex.DecodeString(strings.Repeat("ff", bls.SignatureSize)) + data, _ := cbor.Marshal(inv) + assert.NoError(t, sig2.UnmarshalCBOR(data)) + + _, err = sig2.PointG1() + assert.Error(t, err) +} + +func TestSignatureEqualsTo(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv := ts.RandBLSKeyPair() + sig1 := prv.Sign([]byte("foo")) + sig2 := prv.Sign([]byte("bar")) + + assert.True(t, sig1.EqualsTo(sig1)) + assert.False(t, sig1.EqualsTo(sig2)) + assert.Equal(t, sig1, sig1) + assert.NotEqual(t, sig1, sig2) +} + +func TestSignatureEncoding(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv := ts.RandBLSKeyPair() + sig := prv.Sign(ts.RandBytes(16)) + w1 := util.NewFixedWriter(20) + assert.Error(t, sig.Encode(w1)) + + w2 := util.NewFixedWriter(bls.SignatureSize) + assert.NoError(t, sig.Encode(w2)) + + r1 := util.NewFixedReader(20, w2.Bytes()) + assert.Error(t, sig.Decode(r1)) + + r2 := util.NewFixedReader(bls.SignatureSize, w2.Bytes()) + assert.NoError(t, sig.Decode(r2)) +} + +func TestVerifyingSignature(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + msg := []byte("zarb") + + pb1, pv1 := ts.RandBLSKeyPair() + pb2, pv2 := ts.RandBLSKeyPair() + sig1 := pv1.Sign(msg) + sig2 := pv2.Sign(msg) + + assert.False(t, sig1.EqualsTo(sig2)) + assert.NoError(t, pb1.Verify(msg, sig1)) + assert.NoError(t, pb2.Verify(msg, sig2)) + assert.ErrorIs(t, pb1.Verify(msg, sig2), crypto.ErrInvalidSignature) + assert.ErrorIs(t, pb2.Verify(msg, sig1), crypto.ErrInvalidSignature) + assert.ErrorIs(t, pb1.Verify(msg[1:], sig1), crypto.ErrInvalidSignature) +} + +func TestSignatureBytes(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + bytes []byte + }{ + { + "encoding/hex: invalid byte: U+006E 'n'", + "not_proper_encoded", + false, nil, + }, + { + "signature should be 48 bytes, but it is 0 bytes", + "", + false, nil, + }, + { + "encoding/hex: odd length hex string", + "0", + false, nil, + }, + { + "signature should be 48 bytes, but it is 1 bytes", + "00", + false, nil, + }, + { + "", + "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792", + true, + []byte{ + 0xad, 0x0f, 0x88, 0xce, 0xc8, 0x15, 0xe9, 0xb8, 0xaf, 0x3f, 0x01, 0x36, 0x29, 0x7c, 0xb2, 0x42, + 0xed, 0x8b, 0x63, 0x69, 0xaf, 0x72, 0x3f, 0xbd, 0xac, 0x07, 0x7f, 0xa9, 0x27, 0xf5, 0x78, 0x0d, + 0xb7, 0xdf, 0x47, 0xc7, 0x7f, 0xb5, 0x3f, 0x3a, 0x22, 0x32, 0x46, 0x73, 0xf0, 0x00, 0xc7, 0x92, + }, + }, + } + + for no, test := range tests { + sig, err := bls.SignatureFromString(test.encoded) + if test.valid { + assert.NoError(t, err, "test %v: unexpected error", no) + assert.Equal(t, test.bytes, sig.Bytes(), "test %v: invalid bytes", no) + assert.Equal(t, test.encoded, sig.String(), "test %v: invalid encode", no) + } else { + assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) + } + } +} + +func TestPointG1(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + }{ + { + "compression flag must be set", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + false, + }, + { + "input string must be zero when infinity flag is set", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + false, + }, + { + "signature is zero", + "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + false, + }, + { + "", + "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792", + true, + }, + } + + for no, test := range tests { + sig, err := bls.SignatureFromString(test.encoded) + require.NoError(t, err) + + _, err = sig.PointG1() + if test.valid { + assert.NoError(t, err, "test %v: unexpected error", no) + } else { + assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) + } + } +} diff --git a/util/testsuite/testsuite.go b/util/testsuite/testsuite.go index b717d9467..728fbbd6f 100644 --- a/util/testsuite/testsuite.go +++ b/util/testsuite/testsuite.go @@ -10,6 +10,7 @@ import ( "github.com/pactus-project/pactus/committee" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/sortition" "github.com/pactus-project/pactus/types/account" @@ -236,6 +237,19 @@ func (ts *TestSuite) RandBLSKeyPair() (*bls.PublicKey, *bls.PrivateKey) { return pub, prv } +// RandED25519KeyPair generates a random ED25519 key pair for testing purposes. +func (ts *TestSuite) RandED25519KeyPair() (*ed25519.PublicKey, *ed25519.PrivateKey) { + buf := make([]byte, ed25519.PrivateKeySize) + _, err := ts.Rand.Read(buf) + if err != nil { + panic(err) + } + prv, _ := ed25519.PrivateKeyFromBytes(buf) + pub := prv.PublicKeyNative() + + return pub, prv +} + // RandValKey generates a random validator key for testing purposes. func (ts *TestSuite) RandValKey() *bls.ValidatorKey { _, prv := ts.RandBLSKeyPair() From 1edb585685cae3cbcb671f118185b53fcf16b1ca Mon Sep 17 00:00:00 2001 From: b00f Date: Thu, 22 Aug 2024 14:54:19 +0800 Subject: [PATCH 15/25] test(crypto): add test for hash-to-curve (#1477) --- crypto/bls/bls_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crypto/bls/bls_test.go b/crypto/bls/bls_test.go index 9fd940103..ba4f9a497 100644 --- a/crypto/bls/bls_test.go +++ b/crypto/bls/bls_test.go @@ -145,7 +145,7 @@ func TestDuplicatedAggregate(t *testing.T) { // TestHashToCurve ensures that the hash-to-curve function in kilic/bls12-381 // works as intended and is compatible with the spec. // test vectors can be found here: -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#appendix-J.9.1 +// https://datatracker.ietf.org/doc/html/rfc9380 func TestHashToCurve(t *testing.T) { domain := []byte("QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_") tests := []struct { @@ -173,6 +173,16 @@ func TestHashToCurve(t *testing.T) { "15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488" + "1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38", }, + { + "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "082aabae8b7dedb0e78aeb619ad3bfd9277a2f77ba7fad20ef6aabdc6c31d19ba5a6d12283553294c1825c4b3ca2dcfe" + + "05b84ae5a942248eea39e1d91030458c40153f3b654ab7872d779ad1e942856a20c438e8d99bc8abfbf74729ce1f7ac8", + }, } g1 := bls12381.NewG1() From 0ec6670f0cbb9acc385113ce7fa0ea66844dbfde Mon Sep 17 00:00:00 2001 From: b00f Date: Fri, 23 Aug 2024 17:58:30 +0800 Subject: [PATCH 16/25] test(crypto): update Ed25519 tests (#1483) --- crypto/address.go | 22 ++-- crypto/address_test.go | 12 +- crypto/bls/bls_test.go | 16 +-- crypto/bls/private_key.go | 7 +- crypto/bls/private_key_test.go | 6 +- crypto/bls/public_key.go | 7 +- crypto/bls/public_key_test.go | 6 +- crypto/bls/signature.go | 7 +- crypto/bls/signature_test.go | 17 +-- crypto/ed25519/ed25519_test.go | 181 ++--------------------------- crypto/ed25519/private_key.go | 8 +- crypto/ed25519/private_key_test.go | 58 +++------ crypto/ed25519/public_key.go | 12 +- crypto/ed25519/public_key_test.go | 141 +++++----------------- crypto/ed25519/signature.go | 13 ++- crypto/ed25519/signature_test.go | 104 +++++------------ crypto/hash/hash_test.go | 8 +- network/utils_test.go | 7 +- util/testsuite/testsuite.go | 12 +- wallet/manager.go | 11 +- 20 files changed, 188 insertions(+), 467 deletions(-) diff --git a/crypto/address.go b/crypto/address.go index 06c450d28..536a93505 100644 --- a/crypto/address.go +++ b/crypto/address.go @@ -14,9 +14,10 @@ import ( type AddressType byte const ( - AddressTypeTreasury AddressType = 0 - AddressTypeValidator AddressType = 1 - AddressTypeBLSAccount AddressType = 2 + AddressTypeTreasury AddressType = 0 + AddressTypeValidator AddressType = 1 + AddressTypeBLSAccount AddressType = 2 + AddressTypeEd25519Account AddressType = 3 ) const ( @@ -52,7 +53,11 @@ func AddressFromString(text string) (Address, error) { } // check type is valid - validTypes := []AddressType{AddressTypeValidator, AddressTypeBLSAccount} + validTypes := []AddressType{ + AddressTypeValidator, + AddressTypeBLSAccount, + AddressTypeEd25519Account, + } if !slices.Contains(validTypes, AddressType(typ)) { return Address{}, InvalidAddressTypeError(typ) } @@ -114,7 +119,8 @@ func (addr Address) Encode(w io.Writer) error { case AddressTypeTreasury: return encoding.WriteElement(w, uint8(0)) case AddressTypeValidator, - AddressTypeBLSAccount: + AddressTypeBLSAccount, + AddressTypeEd25519Account: return encoding.WriteElement(w, addr) default: return InvalidAddressTypeError(t) @@ -130,7 +136,8 @@ func (addr *Address) Decode(r io.Reader) error { case AddressTypeTreasury: return nil case AddressTypeValidator, - AddressTypeBLSAccount: + AddressTypeBLSAccount, + AddressTypeEd25519Account: return encoding.ReadElement(r, addr[1:]) default: return InvalidAddressTypeError(t) @@ -143,7 +150,8 @@ func (addr Address) SerializeSize() int { case AddressTypeTreasury: return 1 case AddressTypeValidator, - AddressTypeBLSAccount: + AddressTypeBLSAccount, + AddressTypeEd25519Account: return AddressSize default: return 0 diff --git a/crypto/address_test.go b/crypto/address_test.go index cdb835566..6bc28b3af 100644 --- a/crypto/address_test.go +++ b/crypto/address_test.go @@ -91,8 +91,8 @@ func TestToString(t *testing.T) { nil, }, { - "pc1r0hrct7eflrpw4ccrttxzs4qud2axex4dwc9mn4", - crypto.InvalidAddressTypeError(3), + "pc1y0hrct7eflrpw4ccrttxzs4qud2axex4dksmred", + crypto.InvalidAddressTypeError(4), nil, }, { @@ -137,13 +137,13 @@ func TestAddressEncoding(t *testing.T) { }, { 0, - "030000000000000000000000000000000000000000", - crypto.InvalidAddressTypeError(3), + "040000000000000000000000000000000000000000", + crypto.InvalidAddressTypeError(4), }, { 0, - "03000102030405060708090a0b0c0d0e0f0001020304", - crypto.InvalidAddressTypeError(3), + "04000102030405060708090a0b0c0d0e0f0001020304", + crypto.InvalidAddressTypeError(4), }, { 21, diff --git a/crypto/bls/bls_test.go b/crypto/bls/bls_test.go index ba4f9a497..9ea54f9ac 100644 --- a/crypto/bls/bls_test.go +++ b/crypto/bls/bls_test.go @@ -12,14 +12,14 @@ import ( ) func TestSigning(t *testing.T) { - msg := []byte("zarb") + msg := []byte("pactus") prv, _ := bls.PrivateKeyFromString( "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67") pub, _ := bls.PublicKeyFromString( "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a") sig, _ := bls.SignatureFromString( - "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792") + "923d67a8624cbb7972b29328e15ec76cc846076ccf00a9e94d991c677846f334ae4ba4551396fbcd6d1cab7593baf3b7") addr, _ := crypto.AddressFromString("pc1p5x2a0lkt5nrrdqe0rkcv6r4pfkmdhrr3xk73tq") sig1 := prv.Sign(msg) @@ -30,13 +30,13 @@ func TestSigning(t *testing.T) { } func TestSignatureAggregate(t *testing.T) { - msg := []byte("zarb") + msg := []byte("pactus") prv1, _ := bls.PrivateKeyFromString( "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67") prv2, _ := bls.PrivateKeyFromString( "SECRET1PDUV97560CWDGW2DR453YPUT84REN04G0DZFAPJQL5DV0CKDAN75QCJEV6F") agg, _ := bls.SignatureFromString( - "a390ffec7061827b7e89193a26841dd9e3537b5db0af55661b624e8b93b855e9f65278850002ea72fb3098e674220eca") + "ad747172697127cb08dda29a386e106eb24ab0edfbc044014c3bd7a5f583cc38b3a223ff2c1df9c0b4df110630e6946b") sig1 := prv1.Sign(msg).(*bls.Signature) sig2 := prv2.Sign(msg).(*bls.Signature) @@ -51,8 +51,8 @@ func TestAggregateFailed(t *testing.T) { pub2, prv2 := ts.RandBLSKeyPair() pub3, prv3 := ts.RandBLSKeyPair() pub4, prv4 := ts.RandBLSKeyPair() - msg1 := []byte("zarb") - msg2 := []byte("zarb0") + msg1 := []byte("pactus") + msg2 := []byte("pactus0") sig1 := prv1.Sign(msg1).(*bls.Signature) sig11 := prv1.Sign(msg2).(*bls.Signature) @@ -103,7 +103,7 @@ func TestAggregateOnlyOneSignature(t *testing.T) { ts := testsuite.NewTestSuite(t) _, prv1 := ts.RandBLSKeyPair() - msg1 := []byte("zarb") + msg1 := []byte("pactus") sig1 := prv1.Sign(msg1).(*bls.Signature) agg1 := bls.SignatureAggregate(sig1) @@ -126,7 +126,7 @@ func TestDuplicatedAggregate(t *testing.T) { pub1, prv1 := ts.RandBLSKeyPair() pub2, prv2 := ts.RandBLSKeyPair() - msg1 := []byte("zarb") + msg1 := []byte("pactus") sig1 := prv1.Sign(msg1).(*bls.Signature) sig2 := prv2.Sign(msg1).(*bls.Signature) diff --git a/crypto/bls/private_key.go b/crypto/bls/private_key.go index f0f8a5680..741f1e25c 100644 --- a/crypto/bls/private_key.go +++ b/crypto/bls/private_key.go @@ -161,5 +161,10 @@ func (prv *PrivateKey) PublicKey() crypto.PublicKey { } func (prv *PrivateKey) EqualsTo(x crypto.PrivateKey) bool { - return prv.fr.Equal(&x.(*PrivateKey).fr) + xBLS, ok := x.(*PrivateKey) + if !ok { + return false + } + + return prv.fr.Equal(&xBLS.fr) } diff --git a/crypto/bls/private_key_test.go b/crypto/bls/private_key_test.go index 3d23e7c16..d58361c8e 100644 --- a/crypto/bls/private_key_test.go +++ b/crypto/bls/private_key_test.go @@ -15,14 +15,14 @@ func TestPrivateKeyEqualsTo(t *testing.T) { _, prv1 := ts.RandBLSKeyPair() _, prv2 := ts.RandBLSKeyPair() + _, prv3 := ts.RandEd25519KeyPair() assert.True(t, prv1.EqualsTo(prv1)) assert.False(t, prv1.EqualsTo(prv2)) - assert.Equal(t, prv1, prv1) - assert.NotEqual(t, prv1, prv2) + assert.False(t, prv1.EqualsTo(prv3)) } -func TestPrivateKeyToString(t *testing.T) { +func TestPrivateKeyFromString(t *testing.T) { tests := []struct { errMsg string encoded string diff --git a/crypto/bls/public_key.go b/crypto/bls/public_key.go index 63b4c0157..9d6aa40ac 100644 --- a/crypto/bls/public_key.go +++ b/crypto/bls/public_key.go @@ -141,7 +141,12 @@ func (pub *PublicKey) Verify(msg []byte, sig crypto.Signature) error { // EqualsTo checks if the current public key is equal to another public key. func (pub *PublicKey) EqualsTo(x crypto.PublicKey) bool { - return subtle.ConstantTimeCompare(pub.data, x.(*PublicKey).data) == 1 + xBLS, ok := x.(*PublicKey) + if !ok { + return false + } + + return subtle.ConstantTimeCompare(pub.data, xBLS.data) == 1 } // AccountAddress returns the account address derived from the public key. diff --git a/crypto/bls/public_key_test.go b/crypto/bls/public_key_test.go index 2c3735ba5..4994628f6 100644 --- a/crypto/bls/public_key_test.go +++ b/crypto/bls/public_key_test.go @@ -40,11 +40,11 @@ func TestPublicKeyEqualsTo(t *testing.T) { pub1, _ := ts.RandBLSKeyPair() pub2, _ := ts.RandBLSKeyPair() + pub3, _ := ts.RandEd25519KeyPair() assert.True(t, pub1.EqualsTo(pub1)) assert.False(t, pub1.EqualsTo(pub2)) - assert.Equal(t, pub1, pub1) - assert.NotEqual(t, pub1, pub2) + assert.False(t, pub1.EqualsTo(pub3)) } func TestPublicKeyEncoding(t *testing.T) { @@ -108,7 +108,7 @@ func TestNilSignature(t *testing.T) { assert.Error(t, pub.Verify(nil, &bls.Signature{})) } -func TestPublicKeyBytes(t *testing.T) { +func TestPublicKeyFromString(t *testing.T) { tests := []struct { errMsg string encoded string diff --git a/crypto/bls/signature.go b/crypto/bls/signature.go index 2cf6c1c8b..43cae9f70 100644 --- a/crypto/bls/signature.go +++ b/crypto/bls/signature.go @@ -90,7 +90,12 @@ func (sig *Signature) Decode(r io.Reader) error { // EqualsTo checks if the current signature is equal to another signature. func (sig *Signature) EqualsTo(x crypto.Signature) bool { - return subtle.ConstantTimeCompare(sig.data, x.(*Signature).data) == 1 + xBLS, ok := x.(*Signature) + if !ok { + return false + } + + return subtle.ConstantTimeCompare(sig.data, xBLS.data) == 1 } // PointG1 returns the point on G1 for the signature. diff --git a/crypto/bls/signature_test.go b/crypto/bls/signature_test.go index 7e098275b..17f2c17ee 100644 --- a/crypto/bls/signature_test.go +++ b/crypto/bls/signature_test.go @@ -39,14 +39,17 @@ func TestSignatureCBORMarshaling(t *testing.T) { func TestSignatureEqualsTo(t *testing.T) { ts := testsuite.NewTestSuite(t) - _, prv := ts.RandBLSKeyPair() - sig1 := prv.Sign([]byte("foo")) - sig2 := prv.Sign([]byte("bar")) + _, prv1 := ts.RandBLSKeyPair() + _, prv2 := ts.RandBLSKeyPair() + _, prv3 := ts.RandEd25519KeyPair() + + sig1 := prv1.Sign([]byte("foo")) + sig2 := prv2.Sign([]byte("foo")) + sig3 := prv3.Sign([]byte("foo")) assert.True(t, sig1.EqualsTo(sig1)) assert.False(t, sig1.EqualsTo(sig2)) - assert.Equal(t, sig1, sig1) - assert.NotEqual(t, sig1, sig2) + assert.False(t, sig1.EqualsTo(sig3)) } func TestSignatureEncoding(t *testing.T) { @@ -70,7 +73,7 @@ func TestSignatureEncoding(t *testing.T) { func TestVerifyingSignature(t *testing.T) { ts := testsuite.NewTestSuite(t) - msg := []byte("zarb") + msg := []byte("pactus") pb1, pv1 := ts.RandBLSKeyPair() pb2, pv2 := ts.RandBLSKeyPair() @@ -85,7 +88,7 @@ func TestVerifyingSignature(t *testing.T) { assert.ErrorIs(t, pb1.Verify(msg[1:], sig1), crypto.ErrInvalidSignature) } -func TestSignatureBytes(t *testing.T) { +func TestSignatureFromString(t *testing.T) { tests := []struct { errMsg string encoded string diff --git a/crypto/ed25519/ed25519_test.go b/crypto/ed25519/ed25519_test.go index 6a065c139..39ec879d4 100644 --- a/crypto/ed25519/ed25519_test.go +++ b/crypto/ed25519/ed25519_test.go @@ -1,186 +1,27 @@ package ed25519_test import ( - "encoding/hex" "testing" - bls12381 "github.com/kilic/bls12-381" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" - "github.com/pactus-project/pactus/util/testsuite" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/stretchr/testify/assert" ) func TestSigning(t *testing.T) { - msg := []byte("zarb") - prv, _ := bls.PrivateKeyFromString( - "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67") - pub, _ := bls.PublicKeyFromString( - "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + - "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a") - sig, _ := bls.SignatureFromString( - "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792") - addr, _ := crypto.AddressFromString("pc1p5x2a0lkt5nrrdqe0rkcv6r4pfkmdhrr3xk73tq") + msg := []byte("pactus") + prv, _ := ed25519.PrivateKeyFromString( + "SECRET1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26QUUK3Y0") + pub, _ := ed25519.PublicKeyFromString( + "public1rvqxnpfph8tnc3ck55z85w285t5jetylmmktr9wlzs0zvx7kx500szxfudh") + sig, _ := ed25519.SignatureFromString( + "361aaa09c408bfcf7e79dd90c583eeeaefe7c732ca5643cfb2ea7a6d22105b87" + + "4a412080525a855bbd5df94110a7d0083d6e386e016ecf8b7f522c339f79d305") + addr, _ := crypto.AddressFromString("pc1r7jkvfnegf0rf5ua05fzu9krjhjxcrrygl3v4nl") sig1 := prv.Sign(msg) assert.Equal(t, sig.Bytes(), sig1.Bytes()) assert.NoError(t, pub.Verify(msg, sig)) assert.Equal(t, pub, prv.PublicKey()) - assert.Equal(t, addr, pub.ValidatorAddress()) -} - -func TestSignatureAggregate(t *testing.T) { - msg := []byte("zarb") - prv1, _ := bls.PrivateKeyFromString( - "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67") - prv2, _ := bls.PrivateKeyFromString( - "SECRET1PDUV97560CWDGW2DR453YPUT84REN04G0DZFAPJQL5DV0CKDAN75QCJEV6F") - agg, _ := bls.SignatureFromString( - "a390ffec7061827b7e89193a26841dd9e3537b5db0af55661b624e8b93b855e9f65278850002ea72fb3098e674220eca") - sig1 := prv1.Sign(msg).(*bls.Signature) - sig2 := prv2.Sign(msg).(*bls.Signature) - - assert.True(t, bls.SignatureAggregate(sig1, sig2).EqualsTo(agg)) - assert.False(t, prv1.EqualsTo(prv2)) -} - -func TestAggregateFailed(t *testing.T) { - ts := testsuite.NewTestSuite(t) - - pub1, prv1 := ts.RandBLSKeyPair() - pub2, prv2 := ts.RandBLSKeyPair() - pub3, prv3 := ts.RandBLSKeyPair() - pub4, prv4 := ts.RandBLSKeyPair() - msg1 := []byte("zarb") - msg2 := []byte("zarb0") - - sig1 := prv1.Sign(msg1).(*bls.Signature) - sig11 := prv1.Sign(msg2).(*bls.Signature) - sig2 := prv2.Sign(msg1).(*bls.Signature) - sig3 := prv3.Sign(msg1).(*bls.Signature) - sig4 := prv4.Sign(msg1).(*bls.Signature) - - agg1 := bls.SignatureAggregate(sig1, sig2, sig3) - agg2 := bls.SignatureAggregate(sig1, sig2, sig4) - agg3 := bls.SignatureAggregate(sig11, sig2, sig3) - agg4 := bls.SignatureAggregate(sig1, sig2) - agg5 := bls.SignatureAggregate(sig3, sig2, sig1) - - pubs1 := []*bls.PublicKey{pub1, pub2, pub3} - pubs2 := []*bls.PublicKey{pub1, pub2, pub4} - pubs3 := []*bls.PublicKey{pub1, pub2} - pubs4 := []*bls.PublicKey{pub3, pub2, pub1} - - pubAgg1 := bls.PublicKeyAggregate(pubs1...) - pubAgg2 := bls.PublicKeyAggregate(pubs2...) - pubAgg3 := bls.PublicKeyAggregate(pubs3...) - pubAgg4 := bls.PublicKeyAggregate(pubs4...) - - assert.NoError(t, pub1.Verify(msg1, sig1)) - assert.NoError(t, pub2.Verify(msg1, sig2)) - assert.NoError(t, pub3.Verify(msg1, sig3)) - assert.Error(t, pub2.Verify(msg1, sig1)) - assert.Error(t, pub3.Verify(msg1, sig1)) - assert.Error(t, pub1.Verify(msg1, agg1)) - assert.Error(t, pub2.Verify(msg1, agg1)) - assert.Error(t, pub3.Verify(msg1, agg1)) - - assert.NoError(t, pubAgg1.Verify(msg1, agg1)) - assert.Error(t, pubAgg1.Verify(msg2, agg1)) - assert.Error(t, pubAgg1.Verify(msg1, agg2)) - assert.Error(t, pubAgg2.Verify(msg1, agg1)) - assert.NoError(t, pubAgg2.Verify(msg1, agg2)) - assert.Error(t, pubAgg2.Verify(msg2, agg2)) - assert.Error(t, pubAgg1.Verify(msg1, agg3)) - assert.Error(t, pubAgg1.Verify(msg2, agg3)) - assert.Error(t, pubAgg1.Verify(msg1, agg4)) - assert.Error(t, pubAgg3.Verify(msg1, agg1)) - assert.NoError(t, pubAgg1.Verify(msg1, agg5)) - assert.NoError(t, pubAgg4.Verify(msg1, agg1)) -} - -func TestAggregateOnlyOneSignature(t *testing.T) { - ts := testsuite.NewTestSuite(t) - - _, prv1 := ts.RandBLSKeyPair() - msg1 := []byte("zarb") - sig1 := prv1.Sign(msg1).(*bls.Signature) - agg1 := bls.SignatureAggregate(sig1) - - assert.True(t, agg1.EqualsTo(sig1)) -} - -func TestAggregateOnlyOnePublicKey(t *testing.T) { - ts := testsuite.NewTestSuite(t) - - pub1, _ := ts.RandBLSKeyPair() - agg1 := bls.PublicKeyAggregate(pub1) - - assert.True(t, agg1.EqualsTo(pub1)) -} - -// TODO: should we check for duplication here? -func TestDuplicatedAggregate(t *testing.T) { - ts := testsuite.NewTestSuite(t) - - pub1, prv1 := ts.RandBLSKeyPair() - pub2, prv2 := ts.RandBLSKeyPair() - - msg1 := []byte("zarb") - - sig1 := prv1.Sign(msg1).(*bls.Signature) - sig2 := prv2.Sign(msg1).(*bls.Signature) - - agg1 := bls.SignatureAggregate(sig1, sig2, sig1) - agg2 := bls.SignatureAggregate(sig1, sig2) - assert.False(t, agg1.EqualsTo(agg2)) - - pubs1 := []*bls.PublicKey{pub1, pub2} - pubs2 := []*bls.PublicKey{pub1, pub2, pub1} - pubAgg1 := bls.PublicKeyAggregate(pubs1...) - pubAgg2 := bls.PublicKeyAggregate(pubs2...) - assert.False(t, pubAgg1.EqualsTo(pubAgg2)) -} - -// TestHashToCurve ensures that the hash-to-curve function in kilic/bls12-381 -// works as intended and is compatible with the spec. -// test vectors can be found here: -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#appendix-J.9.1 -func TestHashToCurve(t *testing.T) { - domain := []byte("QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_") - tests := []struct { - msg string - expected string - }{ - { - "", - "052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1" + - "08ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265", - }, - { - "abc", - "03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903" + - "0b9c15f3fe6e5cf4211f346271d7b01c8f3b28be689c8429c85b67af215533311f0b8dfaaa154fa6b88176c229f2885d", - }, - { - "abcdef0123456789", - "11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98" + - "03a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709", - }, - { - "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + - "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", - "15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488" + - "1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38", - }, - } - - g1 := bls12381.NewG1() - for no, test := range tests { - mappedPoint, _ := g1.HashToCurve([]byte(test.msg), domain) - d, _ := hex.DecodeString(test.expected) - expectedPoint, _ := g1.FromBytes(d) - assert.Equal(t, expectedPoint, mappedPoint, - "test %v: not match", no) - } + assert.Equal(t, addr, pub.AccountAddress()) } diff --git a/crypto/ed25519/private_key.go b/crypto/ed25519/private_key.go index 0a0820dde..00576fd54 100644 --- a/crypto/ed25519/private_key.go +++ b/crypto/ed25519/private_key.go @@ -18,7 +18,7 @@ type PrivateKey struct { } // PrivateKeyFromString decodes the input string and returns the PrivateKey -// if the string is a valid bech32m encoding of a BLS public key. +// if the string is a valid bech32m encoding of a Ed25519 public key. func PrivateKeyFromString(text string) (*PrivateKey, error) { // Decode the bech32m encoded private key. hrp, typ, data, err := bech32m.DecodeToBase256WithTypeNoLimit(text) @@ -39,12 +39,6 @@ func PrivateKeyFromString(text string) (*PrivateKey, error) { return PrivateKeyFromBytes(data) } -func KeyGen(seed []byte) (*PrivateKey, error) { - prv := ed25519.NewKeyFromSeed(seed) - - return PrivateKeyFromBytes(prv) -} - // PrivateKeyFromBytes constructs a ED25519 private key from the raw bytes. func PrivateKeyFromBytes(data []byte) (*PrivateKey, error) { if len(data) != PrivateKeySize { diff --git a/crypto/ed25519/private_key_test.go b/crypto/ed25519/private_key_test.go index 447650688..d8a4fac2f 100644 --- a/crypto/ed25519/private_key_test.go +++ b/crypto/ed25519/private_key_test.go @@ -1,8 +1,6 @@ package ed25519_test import ( - "encoding/hex" - "fmt" "strings" "testing" @@ -14,15 +12,13 @@ import ( func TestPrivateKeyEqualsTo(t *testing.T) { ts := testsuite.NewTestSuite(t) - _, prv1 := ts.RandED25519KeyPair() - _, prv2 := ts.RandED25519KeyPair() - - fmt.Println(prv1.String()) + _, prv1 := ts.RandEd25519KeyPair() + _, prv2 := ts.RandEd25519KeyPair() + _, prv3 := ts.RandBLSKeyPair() assert.True(t, prv1.EqualsTo(prv1)) assert.False(t, prv1.EqualsTo(prv2)) - assert.Equal(t, prv1, prv1) - assert.NotEqual(t, prv1, prv2) + assert.False(t, prv1.EqualsTo(prv3)) } func TestPrivateKeyFromString(t *testing.T) { @@ -34,29 +30,27 @@ func TestPrivateKeyFromString(t *testing.T) { }{ { "invalid separator index -1", - "XXXXXXR2SYCC5TDQKMJ73J64J8GJTMTKREEQNQAS0M5SLZ9LVJV7Y940NVZQD9JUS" + - "GV2N44C9H5PVGRXARNGZ7QF3PSKH7805E5SZXPE7ZHHAGX0NFQR", + "not_proper_encoded", false, nil, }, { - "invalid checksum (expected s9c56g got czlgh0)", - "SECRET1RAC7048K666DCCYG7FJW68ZE2G6P32UAPLRLWDV3RTAR4PWZUX2CDSFAL55VM" + - "YS06CY35LA72AWZN5DY5NZA078S4S4K654UFJ0YCCZLGH0", + "invalid checksum (expected uuk3y0 got uuk30y)", + "SECRET1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26QUUK30Y", false, nil, }, { - "invalid bech32 string length 0", - "", + "invalid HRP: xxx", + "XXX1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26Q8JXUV6", false, nil, }, { - "invalid character not part of charset: 105", - "SECRET1IOIOOI", + "invalid private key type: 4", + "SECRET1YVKPE43FDU9TC4C8LPFD4JY9METET3GEKQE7E7ECK4EJYV20WVAPQZCU0KL", false, nil, }, { - "invalid bech32 string length 0", - "SECRET1HPZZU9", + "private key should be 32 bytes, but it is 31 bytes", + "SECRET1RDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CCPV3HNE", false, nil, }, { @@ -64,9 +58,8 @@ func TestPrivateKeyFromString(t *testing.T) { "SECRET1RJ6STNTA7Y3P2QLQF8A6QCX05F2H5TFNE5RSH066KZME4WVFXKE7QW097LG", true, []byte{ - 0x96, 0xa0, 0xb9, 0xaf, 0xbe, 0x24, 0x42, 0xa0, 0x7c, 0x9, 0x3f, 0x74, 0xc, 0x19, 0xf4, - 0x4a, 0xaf, 0x45, 0xa6, 0x79, 0xa0, 0xe1, 0x77, 0xeb, 0x56, 0x16, 0xf3, 0x57, 0x31, 0x26, - 0xb6, 0x7c, + 0x96, 0xa0, 0xb9, 0xaf, 0xbe, 0x24, 0x42, 0xa0, 0x7c, 0x09, 0x3f, 0x74, 0x0c, 0x19, 0xf4, 0x4a, + 0xaf, 0x45, 0xa6, 0x79, 0xa0, 0xe1, 0x77, 0xeb, 0x56, 0x16, 0xf3, 0x57, 0x31, 0x26, 0xb6, 0x7c, }, }, } @@ -82,24 +75,3 @@ func TestPrivateKeyFromString(t *testing.T) { } } } - -// TestKeyGen ensures the KeyGen function works as intended. -func TestKeyGen(t *testing.T) { - tests := []struct { - seed []byte - sk string - }{} - - for i, test := range tests { - prv, err := ed25519.KeyGen(test.seed) - if test.sk == "Err" { - assert.Error(t, err, - "test '%v' failed. no error", i) - } else { - assert.NoError(t, err, - "test'%v' failed. has error", i) - assert.Equal(t, test.sk, hex.EncodeToString(prv.Bytes()), - "test '%v' failed. not equal", i) - } - } -} diff --git a/crypto/ed25519/public_key.go b/crypto/ed25519/public_key.go index 24f0ae2c4..5978a7293 100644 --- a/crypto/ed25519/public_key.go +++ b/crypto/ed25519/public_key.go @@ -22,7 +22,7 @@ type PublicKey struct { } // PublicKeyFromString decodes the input string and returns the PublicKey -// if the string is a valid bech32m encoding of a BLS public key. +// if the string is a valid bech32m encoding of a Ed25519 public key. func PublicKeyFromString(text string) (*PublicKey, error) { // Decode the bech32m encoded public key. hrp, typ, data, err := bech32m.DecodeToBase256WithTypeNoLimit(text) @@ -42,7 +42,7 @@ func PublicKeyFromString(text string) (*PublicKey, error) { return PublicKeyFromBytes(data) } -// PublicKeyFromBytes constructs a BLS public key from the raw bytes. +// PublicKeyFromBytes constructs a Ed25519 public key from the raw bytes. func PublicKeyFromBytes(data []byte) (*PublicKey, error) { if len(data) != PublicKeySize { return nil, errors.Errorf(errors.ErrInvalidPublicKey, @@ -54,14 +54,14 @@ func PublicKeyFromBytes(data []byte) (*PublicKey, error) { // Bytes returns the raw byte representation of the public key. func (pub *PublicKey) Bytes() []byte { - return pub.inner[:PublicKeySize] + return pub.inner } -// String returns a human-readable string for the BLS public key. +// String returns a human-readable string for the Ed25519 public key. func (pub *PublicKey) String() string { str, _ := bech32m.EncodeFromBase256WithType( crypto.PublicKeyHRP, - crypto.SignatureTypeBLS, + crypto.SignatureTypeEd25519, pub.Bytes()) return str @@ -128,7 +128,7 @@ func (pub *PublicKey) EqualsTo(x crypto.PublicKey) bool { // AccountAddress returns the account address derived from the public key. func (pub *PublicKey) AccountAddress() crypto.Address { data := hash.Hash160(hash.Hash256(pub.Bytes())) - addr := crypto.NewAddress(crypto.AddressTypeBLSAccount, data) + addr := crypto.NewAddress(crypto.AddressTypeEd25519Account, data) return addr } diff --git a/crypto/ed25519/public_key_test.go b/crypto/ed25519/public_key_test.go index 2be99a142..ac3ae817f 100644 --- a/crypto/ed25519/public_key_test.go +++ b/crypto/ed25519/public_key_test.go @@ -7,18 +7,17 @@ import ( cbor "github.com/fxamacker/cbor/v2" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/testsuite" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestPublicKeyCBORMarshaling(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub1, _ := ts.RandBLSKeyPair() - pub2 := new(bls.PublicKey) + pub1, _ := ts.RandEd25519KeyPair() + pub2 := new(ed25519.PublicKey) bs, err := pub1.MarshalCBOR() assert.NoError(t, err) @@ -27,88 +26,77 @@ func TestPublicKeyCBORMarshaling(t *testing.T) { assert.Error(t, pub2.UnmarshalCBOR([]byte("abcd"))) - inv, _ := hex.DecodeString(strings.Repeat("ff", bls.PublicKeySize)) + inv, _ := hex.DecodeString(strings.Repeat("ff", ed25519.PublicKeySize)) data, _ := cbor.Marshal(inv) assert.NoError(t, pub2.UnmarshalCBOR(data)) - - _, err = pub2.PointG2() - assert.Error(t, err) } func TestPublicKeyEqualsTo(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub1, _ := ts.RandBLSKeyPair() - pub2, _ := ts.RandBLSKeyPair() + pub1, _ := ts.RandEd25519KeyPair() + pub2, _ := ts.RandEd25519KeyPair() + pub3, _ := ts.RandBLSKeyPair() assert.True(t, pub1.EqualsTo(pub1)) assert.False(t, pub1.EqualsTo(pub2)) - assert.Equal(t, pub1, pub1) - assert.NotEqual(t, pub1, pub2) + assert.False(t, pub1.EqualsTo(pub3)) } func TestPublicKeyEncoding(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub, _ := ts.RandBLSKeyPair() + pub, _ := ts.RandEd25519KeyPair() w1 := util.NewFixedWriter(20) assert.Error(t, pub.Encode(w1)) - w2 := util.NewFixedWriter(bls.PublicKeySize) + w2 := util.NewFixedWriter(ed25519.PublicKeySize) assert.NoError(t, pub.Encode(w2)) r1 := util.NewFixedReader(20, w2.Bytes()) assert.Error(t, pub.Decode(r1)) - r2 := util.NewFixedReader(bls.PublicKeySize, w2.Bytes()) + r2 := util.NewFixedReader(ed25519.PublicKeySize, w2.Bytes()) assert.NoError(t, pub.Decode(r2)) } func TestPublicKeyVerifyAddress(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub1, _ := ts.RandBLSKeyPair() - pub2, _ := ts.RandBLSKeyPair() + pub1, _ := ts.RandEd25519KeyPair() + pub2, _ := ts.RandEd25519KeyPair() err := pub1.VerifyAddress(pub1.AccountAddress()) assert.NoError(t, err) - err = pub1.VerifyAddress(pub1.ValidatorAddress()) - assert.NoError(t, err) err = pub1.VerifyAddress(pub2.AccountAddress()) assert.Equal(t, crypto.AddressMismatchError{ Expected: pub1.AccountAddress(), Got: pub2.AccountAddress(), }, err) - - err = pub1.VerifyAddress(pub2.ValidatorAddress()) - assert.Equal(t, crypto.AddressMismatchError{ - Expected: pub1.ValidatorAddress(), - Got: pub2.ValidatorAddress(), - }, err) } func TestNilPublicKey(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub := &bls.PublicKey{} - randSig := ts.RandBLSSignature() + pub, _ := ts.RandEd25519KeyPair() + randSig := ts.RandEd25519Signature() assert.Error(t, pub.VerifyAddress(ts.RandAccAddress())) assert.Error(t, pub.VerifyAddress(ts.RandValAddress())) assert.Error(t, pub.Verify(nil, nil)) - assert.Error(t, pub.Verify(nil, &bls.Signature{})) assert.Error(t, pub.Verify(nil, randSig)) } func TestNilSignature(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub, _ := ts.RandBLSKeyPair() + pub, _ := ts.RandEd25519KeyPair() + randSig := ts.RandEd25519Signature() assert.Error(t, pub.Verify(nil, nil)) - assert.Error(t, pub.Verify(nil, &bls.Signature{})) + assert.Error(t, pub.Verify(nil, randSig)) } -func TestPublicKeyBytes(t *testing.T) { +func TestPublicKeyFromString(t *testing.T) { tests := []struct { errMsg string encoded string @@ -121,62 +109,38 @@ func TestPublicKeyBytes(t *testing.T) { false, nil, }, { - "invalid bech32 string length 0", - "", - false, nil, - }, - { - "invalid character not part of charset: 105", - "public1ioiooi", - false, nil, - }, - { - "invalid bech32 string length 0", - "public134jkgz", + "invalid checksum (expected ztd56p got ztd5p6)", + "public1rafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qztd5p6", false, nil, }, { "invalid HRP: xxx", - "xxx1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjrvqc" + - "vf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5evslaq", - false, nil, - }, - { - "invalid checksum (expected jhx47a got jhx470)", - "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + - "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx470", + "xxx1rafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qvguamu", false, nil, }, { - "public key should be 96 bytes, but it is 95 bytes", - "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + - "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg73y98kl", + "public key should be 32 bytes, but it is 31 bytes", + "public1ruwz86xyvhyehy8g7wg98jsmy07cfkjp6dy8zwxa8hqtdj99hquk7xyus", false, nil, }, { - "invalid public key type: 2", - "public1z372l5frmm5e7cn7ewfjdkx5t7y62kztqr82rtatat70cl8p8ng3rdzr02mzpwcfl6s2v26kry6mwg" + - "xpqy92ywx9wtff80mc9p3kr4cmhgekj048gavx2zdh78tsnh7eg5jzdw6s3et6c0dqyp22vslcgkukxh4l4", + "invalid public key type: 4", + "public1yafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qdnx0mf", false, nil, }, { "", - "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + - "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a", + "public1rafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qztd56p", true, []byte{ - 0xaf, 0x0f, 0x74, 0x91, 0x7f, 0x50, 0x65, 0xaf, 0x94, 0x72, 0x7a, 0xe9, 0x54, 0x1b, 0x0d, 0xdc, - 0xfb, 0x5b, 0x82, 0x8a, 0x9e, 0x01, 0x6b, 0x02, 0x49, 0x8f, 0x47, 0x7e, 0xd3, 0x7f, 0xb4, 0x4d, 0x5d, - 0x88, 0x24, 0x95, 0xaf, 0xb6, 0xfd, 0x4f, 0x97, 0x73, 0xe4, 0xea, 0x9d, 0xee, 0xe4, 0x36, 0x03, 0x0c, - 0x4d, 0x61, 0xc6, 0xe3, 0xa1, 0x15, 0x15, 0x85, 0xe1, 0xd8, 0x38, 0xca, 0xe1, 0x44, 0x4a, 0x43, 0x8d, - 0x08, 0x9c, 0xe7, 0x7e, 0x10, 0xc4, 0x92, 0xa5, 0x5f, 0x69, 0x08, 0x12, 0x5c, 0x5b, 0xe9, 0xb2, 0x36, - 0xa2, 0x46, 0xe4, 0x08, 0x2d, 0x08, 0xde, 0x56, 0x4e, 0x11, 0x1e, 0x65, + 0xea, 0x67, 0xf8, 0xaa, 0xbc, 0x74, 0xd0, 0x06, 0x82, 0xb4, 0xa7, 0x4d, 0x5c, 0xd1, 0x49, 0xcb, + 0x76, 0x9c, 0x32, 0x16, 0xb3, 0xbb, 0x0d, 0x3a, 0x1d, 0xe3, 0xf8, 0xf9, 0xba, 0x55, 0x41, 0x74, }, }, } for no, test := range tests { - pub, err := bls.PublicKeyFromString(test.encoded) + pub, err := ed25519.PublicKeyFromString(test.encoded) if test.valid { assert.NoError(t, err, "test %v: unexpected error", no) assert.Equal(t, test.result, pub.Bytes(), "test %v: invalid bytes", no) @@ -186,48 +150,3 @@ func TestPublicKeyBytes(t *testing.T) { } } } - -func TestPointG2(t *testing.T) { - tests := []struct { - errMsg string - encoded string - valid bool - }{ - { - "compression flag must be set", - "public1pqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + - "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqjzu9w8", - false, - }, - { - "input string must be zero when infinity flag is set", - "public1pllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll" + - "llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllluhpuzyf", - false, - }, - { - "public key is zero", - "public1pcqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + - "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqglnhh9", - false, - }, - { - "", - "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjr" + - "vqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a", - true, - }, - } - - for no, test := range tests { - pub, err := bls.PublicKeyFromString(test.encoded) - require.NoError(t, err) - - _, err = pub.PointG2() - if test.valid { - assert.NoError(t, err, "test %v: unexpected error", no) - } else { - assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) - } - } -} diff --git a/crypto/ed25519/signature.go b/crypto/ed25519/signature.go index 98c08d2d6..76c38b01b 100644 --- a/crypto/ed25519/signature.go +++ b/crypto/ed25519/signature.go @@ -21,7 +21,7 @@ type Signature struct { } // SignatureFromString decodes the input string and returns the Signature -// if the string is a valid hexadecimal encoding of a BLS signature. +// if the string is a valid hexadecimal encoding of a Ed25519 signature. func SignatureFromString(text string) (*Signature, error) { data, err := hex.DecodeString(text) if err != nil { @@ -31,7 +31,7 @@ func SignatureFromString(text string) (*Signature, error) { return SignatureFromBytes(data) } -// SignatureFromBytes constructs a BLS signature from the raw bytes. +// SignatureFromBytes constructs a Ed25519 signature from the raw bytes. func SignatureFromBytes(data []byte) (*Signature, error) { if len(data) != SignatureSize { return nil, errors.Errorf(errors.ErrInvalidSignature, @@ -86,6 +86,11 @@ func (sig *Signature) Decode(r io.Reader) error { } // EqualsTo checks if the current signature is equal to another signature. -func (sig *Signature) EqualsTo(right crypto.Signature) bool { - return subtle.ConstantTimeCompare(sig.data, right.(*Signature).data) == 1 +func (sig *Signature) EqualsTo(x crypto.Signature) bool { + xEd25519, ok := x.(*Signature) + if !ok { + return false + } + + return subtle.ConstantTimeCompare(sig.data, xEd25519.data) == 1 } diff --git a/crypto/ed25519/signature_test.go b/crypto/ed25519/signature_test.go index 78bc94803..1d507c08c 100644 --- a/crypto/ed25519/signature_test.go +++ b/crypto/ed25519/signature_test.go @@ -7,19 +7,18 @@ import ( cbor "github.com/fxamacker/cbor/v2" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/util" "github.com/pactus-project/pactus/util/testsuite" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSignatureCBORMarshaling(t *testing.T) { ts := testsuite.NewTestSuite(t) - _, prv := ts.RandBLSKeyPair() + _, prv := ts.RandEd25519KeyPair() sig1 := prv.Sign(ts.RandBytes(16)) - sig2 := new(bls.Signature) + sig2 := new(ed25519.Signature) bs, err := sig1.MarshalCBOR() assert.NoError(t, err) @@ -28,52 +27,52 @@ func TestSignatureCBORMarshaling(t *testing.T) { assert.Error(t, sig2.UnmarshalCBOR([]byte("abcd"))) - inv, _ := hex.DecodeString(strings.Repeat("ff", bls.SignatureSize)) + inv, _ := hex.DecodeString(strings.Repeat("ff", ed25519.SignatureSize)) data, _ := cbor.Marshal(inv) assert.NoError(t, sig2.UnmarshalCBOR(data)) - - _, err = sig2.PointG1() - assert.Error(t, err) } func TestSignatureEqualsTo(t *testing.T) { ts := testsuite.NewTestSuite(t) - _, prv := ts.RandBLSKeyPair() - sig1 := prv.Sign([]byte("foo")) - sig2 := prv.Sign([]byte("bar")) + _, prv1 := ts.RandEd25519KeyPair() + _, prv2 := ts.RandEd25519KeyPair() + _, prv3 := ts.RandBLSKeyPair() + + sig1 := prv1.Sign([]byte("foo")) + sig2 := prv2.Sign([]byte("foo")) + sig3 := prv3.Sign([]byte("foo")) assert.True(t, sig1.EqualsTo(sig1)) assert.False(t, sig1.EqualsTo(sig2)) - assert.Equal(t, sig1, sig1) - assert.NotEqual(t, sig1, sig2) + assert.False(t, sig1.EqualsTo(sig3)) } func TestSignatureEncoding(t *testing.T) { ts := testsuite.NewTestSuite(t) - _, prv := ts.RandBLSKeyPair() + _, prv := ts.RandEd25519KeyPair() sig := prv.Sign(ts.RandBytes(16)) w1 := util.NewFixedWriter(20) assert.Error(t, sig.Encode(w1)) - w2 := util.NewFixedWriter(bls.SignatureSize) + w2 := util.NewFixedWriter(ed25519.SignatureSize) assert.NoError(t, sig.Encode(w2)) r1 := util.NewFixedReader(20, w2.Bytes()) assert.Error(t, sig.Decode(r1)) - r2 := util.NewFixedReader(bls.SignatureSize, w2.Bytes()) + r2 := util.NewFixedReader(ed25519.SignatureSize, w2.Bytes()) assert.NoError(t, sig.Decode(r2)) } func TestVerifyingSignature(t *testing.T) { ts := testsuite.NewTestSuite(t) - msg := []byte("zarb") + msg := []byte("pactus") - pb1, pv1 := ts.RandBLSKeyPair() - pb2, pv2 := ts.RandBLSKeyPair() + pb1, pv1 := ts.RandEd25519KeyPair() + pb2, pv2 := ts.RandEd25519KeyPair() sig1 := pv1.Sign(msg) sig2 := pv2.Sign(msg) @@ -85,7 +84,7 @@ func TestVerifyingSignature(t *testing.T) { assert.ErrorIs(t, pb1.Verify(msg[1:], sig1), crypto.ErrInvalidSignature) } -func TestSignatureBytes(t *testing.T) { +func TestSignatureFromString(t *testing.T) { tests := []struct { errMsg string encoded string @@ -98,34 +97,26 @@ func TestSignatureBytes(t *testing.T) { false, nil, }, { - "signature should be 48 bytes, but it is 0 bytes", + "signature should be 64 bytes, but it is 0 bytes", "", false, nil, }, - { - "encoding/hex: odd length hex string", - "0", - false, nil, - }, - { - "signature should be 48 bytes, but it is 1 bytes", - "00", - false, nil, - }, { "", - "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792", + "7d6af02f788422319781b03d7f4ed575b78c4c4dc8060ce145624fc8dc9ad92b" + + "ae2d28c70242f03a644f313009ad9cc88b5dc37d501e43279c8fbc40b973af04", true, []byte{ - 0xad, 0x0f, 0x88, 0xce, 0xc8, 0x15, 0xe9, 0xb8, 0xaf, 0x3f, 0x01, 0x36, 0x29, 0x7c, 0xb2, 0x42, - 0xed, 0x8b, 0x63, 0x69, 0xaf, 0x72, 0x3f, 0xbd, 0xac, 0x07, 0x7f, 0xa9, 0x27, 0xf5, 0x78, 0x0d, - 0xb7, 0xdf, 0x47, 0xc7, 0x7f, 0xb5, 0x3f, 0x3a, 0x22, 0x32, 0x46, 0x73, 0xf0, 0x00, 0xc7, 0x92, + 0x7d, 0x6a, 0xf0, 0x2f, 0x78, 0x84, 0x22, 0x31, 0x97, 0x81, 0xb0, 0x3d, 0x7f, 0x4e, 0xd5, 0x75, + 0xb7, 0x8c, 0x4c, 0x4d, 0xc8, 0x06, 0x0c, 0xe1, 0x45, 0x62, 0x4f, 0xc8, 0xdc, 0x9a, 0xd9, 0x2b, + 0xae, 0x2d, 0x28, 0xc7, 0x02, 0x42, 0xf0, 0x3a, 0x64, 0x4f, 0x31, 0x30, 0x09, 0xad, 0x9c, 0xc8, + 0x8b, 0x5d, 0xc3, 0x7d, 0x50, 0x1e, 0x43, 0x27, 0x9c, 0x8f, 0xbc, 0x40, 0xb9, 0x73, 0xaf, 0x04, }, }, } for no, test := range tests { - sig, err := bls.SignatureFromString(test.encoded) + sig, err := ed25519.SignatureFromString(test.encoded) if test.valid { assert.NoError(t, err, "test %v: unexpected error", no) assert.Equal(t, test.bytes, sig.Bytes(), "test %v: invalid bytes", no) @@ -135,44 +126,3 @@ func TestSignatureBytes(t *testing.T) { } } } - -func TestPointG1(t *testing.T) { - tests := []struct { - errMsg string - encoded string - valid bool - }{ - { - "compression flag must be set", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - false, - }, - { - "input string must be zero when infinity flag is set", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - false, - }, - { - "signature is zero", - "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - false, - }, - { - "", - "ad0f88cec815e9b8af3f0136297cb242ed8b6369af723fbdac077fa927f5780db7df47c77fb53f3a22324673f000c792", - true, - }, - } - - for no, test := range tests { - sig, err := bls.SignatureFromString(test.encoded) - require.NoError(t, err) - - _, err = sig.PointG1() - if test.valid { - assert.NoError(t, err, "test %v: unexpected error", no) - } else { - assert.Contains(t, err.Error(), test.errMsg, "test %v: error not matched", no) - } - } -} diff --git a/crypto/hash/hash_test.go b/crypto/hash/hash_test.go index 18f8e0b36..e45aaf3c6 100644 --- a/crypto/hash/hash_test.go +++ b/crypto/hash/hash_test.go @@ -38,16 +38,16 @@ func TestHashEmpty(t *testing.T) { } func TestHash256(t *testing.T) { - data := []byte("zarb") + data := []byte("pactus") h1 := hash.Hash256(data) - expected, _ := hex.DecodeString("12b38977f2d67f06f0c0cd54aaf7324cf4fee184398ea33d295e8d1543c2ee1a") + expected, _ := hex.DecodeString("ea020ace5c968f755dfc1b5921e574191cd9ff438639badae8a69f667e0d5970") assert.Equal(t, expected, h1) } func TestHash160(t *testing.T) { - data := []byte("zarb") + data := []byte("pactus") h := hash.Hash160(data) - expected, _ := hex.DecodeString("e93efc0c83176034cb828e39435eeecc07a29298") + expected, _ := hex.DecodeString("1e4633f850c9590a97633631eae007e18648e30e") assert.Equal(t, expected, h) } diff --git a/network/utils_test.go b/network/utils_test.go index d9d5319ee..6f03b8909 100644 --- a/network/utils_test.go +++ b/network/utils_test.go @@ -156,8 +156,11 @@ func TestSubnetsToFilters(t *testing.T) { } func TestMessageIdFunc(t *testing.T) { - m := &lp2pspb.Message{Data: []byte("zarb")} + m := &lp2pspb.Message{Data: []byte("pactus")} id := MessageIDFunc(m) - assert.Equal(t, id, "\x12\xb3\x89\x77\xf2\xd6\x7f\x06\xf0\xc0\xcd\x54\xaa\xf7\x32\x4c\xf4\xfe\xe1\x84") + assert.Equal(t, id, string([]byte{ + 0xea, 0x02, 0x0a, 0xce, 0x5c, 0x96, 0x8f, 0x75, + 0x5d, 0xfc, 0x1b, 0x59, 0x21, 0xe5, 0x74, 0x19, 0x1c, 0xd9, 0xff, 0x43, + })) } diff --git a/util/testsuite/testsuite.go b/util/testsuite/testsuite.go index 728fbbd6f..3ab7d7bfc 100644 --- a/util/testsuite/testsuite.go +++ b/util/testsuite/testsuite.go @@ -237,8 +237,8 @@ func (ts *TestSuite) RandBLSKeyPair() (*bls.PublicKey, *bls.PrivateKey) { return pub, prv } -// RandED25519KeyPair generates a random ED25519 key pair for testing purposes. -func (ts *TestSuite) RandED25519KeyPair() (*ed25519.PublicKey, *ed25519.PrivateKey) { +// RandEd25519KeyPair generates a random Ed25519 key pair for testing purposes. +func (ts *TestSuite) RandEd25519KeyPair() (*ed25519.PublicKey, *ed25519.PrivateKey) { buf := make([]byte, ed25519.PrivateKeySize) _, err := ts.Rand.Read(buf) if err != nil { @@ -265,6 +265,14 @@ func (ts *TestSuite) RandBLSSignature() *bls.Signature { return sig.(*bls.Signature) } +// RandEd25519Signature generates a random BLS signature for testing purposes. +func (ts *TestSuite) RandEd25519Signature() *ed25519.Signature { + _, prv := ts.RandEd25519KeyPair() + sig := prv.Sign(ts.RandBytes(8)) + + return sig.(*ed25519.Signature) +} + // RandHash generates a random hash for testing purposes. func (ts *TestSuite) RandHash() hash.Hash { return hash.CalcHash(util.Int64ToSlice(ts.RandInt64(util.MaxInt64))) diff --git a/wallet/manager.go b/wallet/manager.go index eef29ea88..50dca6f97 100644 --- a/wallet/manager.go +++ b/wallet/manager.go @@ -153,20 +153,23 @@ func (wm *Manager) GetNewAddress( var addressInfo *vault.AddressInfo switch addressType { - case crypto.AddressTypeBLSAccount: - info, err := wlt.NewBLSAccountAddress(label) + case crypto.AddressTypeValidator: + info, err := wlt.NewValidatorAddress(label) if err != nil { return nil, err } addressInfo = info - case crypto.AddressTypeValidator: - info, err := wlt.NewValidatorAddress(label) + case crypto.AddressTypeBLSAccount: + info, err := wlt.NewBLSAccountAddress(label) if err != nil { return nil, err } addressInfo = info + case crypto.AddressTypeEd25519Account: + return nil, status.Errorf(codes.InvalidArgument, "not supported yet") + case crypto.AddressTypeTreasury: return nil, status.Errorf(codes.InvalidArgument, "invalid address type") From 4e7052d53cff6174854ee0dd8e851ce0749d9197 Mon Sep 17 00:00:00 2001 From: Maxi Date: Fri, 23 Aug 2024 18:25:42 +0200 Subject: [PATCH 17/25] feat(grpc): add `Proposal` to `ConsensusInfo` API (#1469) --- www/grpc/blockchain.go | 26 +- www/grpc/gen/dart/blockchain.pb.dart | 105 ++ www/grpc/gen/dart/blockchain.pbjson.dart | 17 +- www/grpc/gen/docs/grpc.md | 37 +- www/grpc/gen/docs/json-rpc.md | 37 +- www/grpc/gen/go/blockchain.pb.go | 490 +++-- .../blockchain/BlockchainOuterClass.java | 1583 +++++++++++++++-- www/grpc/gen/js/blockchain_pb.js | 295 ++- www/grpc/gen/python/blockchain_pb2.py | 50 +- www/grpc/gen/rust/pactus.rs | 20 + www/grpc/gen/rust/pactus.serde.rs | 165 ++ www/grpc/proto/blockchain.proto | 18 +- www/grpc/swagger-ui/pactus.swagger.json | 28 + www/http/blockchain.go | 9 + 14 files changed, 2484 insertions(+), 396 deletions(-) diff --git a/www/grpc/blockchain.go b/www/grpc/blockchain.go index c01736c73..a422abc15 100644 --- a/www/grpc/blockchain.go +++ b/www/grpc/blockchain.go @@ -51,6 +51,8 @@ func (s *blockchainServer) GetConsensusInfo(_ context.Context, _ *pactus.GetConsensusInfoRequest, ) (*pactus.GetConsensusInfoResponse, error) { instances := make([]*pactus.ConsensusInfo, 0) + var proposal *pactus.Proposal + for _, cons := range s.consMgr.Instances() { height, round := cons.HeightRound() votes := cons.AllVotes() @@ -67,9 +69,31 @@ func (s *blockchainServer) GetConsensusInfo(_ context.Context, Round: int32(round), Votes: voteInfos, }) + + if proposal == nil && cons.Proposal() != nil { + // All instances have the same proposal, so we just need to fill proposal once. + p := cons.Proposal() + + var blockData string + if p.Block() != nil { + data, err := p.Block().Bytes() + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + blockData = string(data) + } + + proposal = &pactus.Proposal{ + Height: p.Height(), + Round: int32(p.Round()), + BlockData: blockData, + SignatureData: string(p.Signature().Bytes()), + } + } } - return &pactus.GetConsensusInfoResponse{Instances: instances}, nil + return &pactus.GetConsensusInfoResponse{Instances: instances, Proposal: proposal}, nil } func (s *blockchainServer) GetBlockHash(_ context.Context, diff --git a/www/grpc/gen/dart/blockchain.pb.dart b/www/grpc/gen/dart/blockchain.pb.dart index 34e41f776..8ecf905fb 100644 --- a/www/grpc/gen/dart/blockchain.pb.dart +++ b/www/grpc/gen/dart/blockchain.pb.dart @@ -1027,17 +1027,22 @@ class GetConsensusInfoRequest extends $pb.GeneratedMessage { class GetConsensusInfoResponse extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetConsensusInfoResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'pactus'), createEmptyInstance: create) ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'instances', $pb.PbFieldType.PM, subBuilder: ConsensusInfo.create) + ..aOM(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'proposal', subBuilder: Proposal.create) ..hasRequiredFields = false ; GetConsensusInfoResponse._() : super(); factory GetConsensusInfoResponse({ $core.Iterable? instances, + Proposal? proposal, }) { final _result = create(); if (instances != null) { _result.instances.addAll(instances); } + if (proposal != null) { + _result.proposal = proposal; + } return _result; } factory GetConsensusInfoResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -1063,6 +1068,17 @@ class GetConsensusInfoResponse extends $pb.GeneratedMessage { @$pb.TagNumber(1) $core.List get instances => $_getList(0); + + @$pb.TagNumber(6) + Proposal get proposal => $_getN(1); + @$pb.TagNumber(6) + set proposal(Proposal v) { setField(6, v); } + @$pb.TagNumber(6) + $core.bool hasProposal() => $_has(1); + @$pb.TagNumber(6) + void clearProposal() => clearField(6); + @$pb.TagNumber(6) + Proposal ensureProposal() => $_ensure(1); } class GetTxPoolContentRequest extends $pb.GeneratedMessage { @@ -1837,6 +1853,95 @@ class ConsensusInfo extends $pb.GeneratedMessage { $core.List get votes => $_getList(4); } +class Proposal extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Proposal', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'pactus'), createEmptyInstance: create) + ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'height', $pb.PbFieldType.OU3) + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'round', $pb.PbFieldType.O3) + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockData') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signatureData') + ..hasRequiredFields = false + ; + + Proposal._() : super(); + factory Proposal({ + $core.int? height, + $core.int? round, + $core.String? blockData, + $core.String? signatureData, + }) { + final _result = create(); + if (height != null) { + _result.height = height; + } + if (round != null) { + _result.round = round; + } + if (blockData != null) { + _result.blockData = blockData; + } + if (signatureData != null) { + _result.signatureData = signatureData; + } + return _result; + } + factory Proposal.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Proposal.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + Proposal clone() => Proposal()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + Proposal copyWith(void Function(Proposal) updates) => super.copyWith((message) => updates(message as Proposal)) as Proposal; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static Proposal create() => Proposal._(); + Proposal createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static Proposal getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Proposal? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get height => $_getIZ(0); + @$pb.TagNumber(1) + set height($core.int v) { $_setUnsignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasHeight() => $_has(0); + @$pb.TagNumber(1) + void clearHeight() => clearField(1); + + @$pb.TagNumber(2) + $core.int get round => $_getIZ(1); + @$pb.TagNumber(2) + set round($core.int v) { $_setSignedInt32(1, v); } + @$pb.TagNumber(2) + $core.bool hasRound() => $_has(1); + @$pb.TagNumber(2) + void clearRound() => clearField(2); + + @$pb.TagNumber(3) + $core.String get blockData => $_getSZ(2); + @$pb.TagNumber(3) + set blockData($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasBlockData() => $_has(2); + @$pb.TagNumber(3) + void clearBlockData() => clearField(3); + + @$pb.TagNumber(4) + $core.String get signatureData => $_getSZ(3); + @$pb.TagNumber(4) + set signatureData($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasSignatureData() => $_has(3); + @$pb.TagNumber(4) + void clearSignatureData() => clearField(4); +} + class BlockchainApi { $pb.RpcClient _client; BlockchainApi(this._client); diff --git a/www/grpc/gen/dart/blockchain.pbjson.dart b/www/grpc/gen/dart/blockchain.pbjson.dart index ee97ec9d3..efffe6152 100644 --- a/www/grpc/gen/dart/blockchain.pbjson.dart +++ b/www/grpc/gen/dart/blockchain.pbjson.dart @@ -227,11 +227,12 @@ const GetConsensusInfoResponse$json = const { '1': 'GetConsensusInfoResponse', '2': const [ const {'1': 'instances', '3': 1, '4': 3, '5': 11, '6': '.pactus.ConsensusInfo', '10': 'instances'}, + const {'1': 'proposal', '3': 6, '4': 1, '5': 11, '6': '.pactus.Proposal', '10': 'proposal'}, ], }; /// Descriptor for `GetConsensusInfoResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List getConsensusInfoResponseDescriptor = $convert.base64Decode('ChhHZXRDb25zZW5zdXNJbmZvUmVzcG9uc2USMwoJaW5zdGFuY2VzGAEgAygLMhUucGFjdHVzLkNvbnNlbnN1c0luZm9SCWluc3RhbmNlcw=='); +final $typed_data.Uint8List getConsensusInfoResponseDescriptor = $convert.base64Decode('ChhHZXRDb25zZW5zdXNJbmZvUmVzcG9uc2USMwoJaW5zdGFuY2VzGAEgAygLMhUucGFjdHVzLkNvbnNlbnN1c0luZm9SCWluc3RhbmNlcxIsCghwcm9wb3NhbBgGIAEoCzIQLnBhY3R1cy5Qcm9wb3NhbFIIcHJvcG9zYWw='); @$core.Deprecated('Use getTxPoolContentRequestDescriptor instead') const GetTxPoolContentRequest$json = const { '1': 'GetTxPoolContentRequest', @@ -342,6 +343,19 @@ const ConsensusInfo$json = const { /// Descriptor for `ConsensusInfo`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List consensusInfoDescriptor = $convert.base64Decode('Cg1Db25zZW5zdXNJbmZvEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3MSFgoGYWN0aXZlGAIgASgIUgZhY3RpdmUSFgoGaGVpZ2h0GAMgASgNUgZoZWlnaHQSFAoFcm91bmQYBCABKAVSBXJvdW5kEiYKBXZvdGVzGAUgAygLMhAucGFjdHVzLlZvdGVJbmZvUgV2b3Rlcw=='); +@$core.Deprecated('Use proposalDescriptor instead') +const Proposal$json = const { + '1': 'Proposal', + '2': const [ + const {'1': 'height', '3': 1, '4': 1, '5': 13, '10': 'height'}, + const {'1': 'round', '3': 2, '4': 1, '5': 5, '10': 'round'}, + const {'1': 'block_data', '3': 3, '4': 1, '5': 9, '10': 'blockData'}, + const {'1': 'signature_data', '3': 4, '4': 1, '5': 9, '10': 'signatureData'}, + ], +}; + +/// Descriptor for `Proposal`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List proposalDescriptor = $convert.base64Decode('CghQcm9wb3NhbBIWCgZoZWlnaHQYASABKA1SBmhlaWdodBIUCgVyb3VuZBgCIAEoBVIFcm91bmQSHQoKYmxvY2tfZGF0YRgDIAEoCVIJYmxvY2tEYXRhEiUKDnNpZ25hdHVyZV9kYXRhGAQgASgJUg1zaWduYXR1cmVEYXRh'); const $core.Map<$core.String, $core.dynamic> BlockchainServiceBase$json = const { '1': 'Blockchain', '2': const [ @@ -382,6 +396,7 @@ const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> Blockchain '.pactus.GetConsensusInfoResponse': GetConsensusInfoResponse$json, '.pactus.ConsensusInfo': ConsensusInfo$json, '.pactus.VoteInfo': VoteInfo$json, + '.pactus.Proposal': Proposal$json, '.pactus.GetAccountRequest': GetAccountRequest$json, '.pactus.GetAccountResponse': GetAccountResponse$json, '.pactus.AccountInfo': AccountInfo$json, diff --git a/www/grpc/gen/docs/grpc.md b/www/grpc/gen/docs/grpc.md index 583f0ef30..f7c5ca49f 100644 --- a/www/grpc/gen/docs/grpc.md +++ b/www/grpc/gen/docs/grpc.md @@ -1513,7 +1513,42 @@ committee. The change-proposer value of the vote. - + + proposal + Proposal + + The proposal of the consensus info. + + + + proposal.height + uint32 + + The height of the proposal. + + + + proposal.round + int32 + + The round of the proposal. + + + + proposal.block_data + string + + The block data of the proposal. + + + + proposal.signature_data + string + + The signature data of the proposal. + + + ### GetAccount diff --git a/www/grpc/gen/docs/json-rpc.md b/www/grpc/gen/docs/json-rpc.md index 800aa3dc7..a28e42013 100644 --- a/www/grpc/gen/docs/json-rpc.md +++ b/www/grpc/gen/docs/json-rpc.md @@ -1564,7 +1564,42 @@ committee. The change-proposer value of the vote. - + + proposal + object + + The proposal of the consensus info. + + + + proposal.height + numeric + + The height of the proposal. + + + + proposal.round + numeric + + The round of the proposal. + + + + proposal.block_data + string + + The block data of the proposal. + + + + proposal.signature_data + string + + The signature data of the proposal. + + + ### pactus.blockchain.get_account diff --git a/www/grpc/gen/go/blockchain.pb.go b/www/grpc/gen/go/blockchain.pb.go index 54adbf252..57b401540 100644 --- a/www/grpc/gen/go/blockchain.pb.go +++ b/www/grpc/gen/go/blockchain.pb.go @@ -1135,6 +1135,8 @@ type GetConsensusInfoResponse struct { // List of consensus instances. Instances []*ConsensusInfo `protobuf:"bytes,1,rep,name=instances,proto3" json:"instances,omitempty"` + // The proposal of the consensus info. + Proposal *Proposal `protobuf:"bytes,6,opt,name=proposal,proto3" json:"proposal,omitempty"` } func (x *GetConsensusInfoResponse) Reset() { @@ -1176,6 +1178,13 @@ func (x *GetConsensusInfoResponse) GetInstances() []*ConsensusInfo { return nil } +func (x *GetConsensusInfoResponse) GetProposal() *Proposal { + if x != nil { + return x.Proposal + } + return nil +} + // Request message to retrieve transactions in the transaction pool. type GetTxPoolContentRequest struct { state protoimpl.MessageState @@ -1840,6 +1849,82 @@ func (x *ConsensusInfo) GetVotes() []*VoteInfo { return nil } +// Message containing information about a proposal. +type Proposal struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The height of the proposal. + Height uint32 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + // The round of the proposal. + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + // The block data of the proposal. + BlockData string `protobuf:"bytes,3,opt,name=block_data,json=blockData,proto3" json:"block_data,omitempty"` + // The signature data of the proposal. + SignatureData string `protobuf:"bytes,4,opt,name=signature_data,json=signatureData,proto3" json:"signature_data,omitempty"` +} + +func (x *Proposal) Reset() { + *x = Proposal{} + if protoimpl.UnsafeEnabled { + mi := &file_blockchain_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Proposal) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Proposal) ProtoMessage() {} + +func (x *Proposal) ProtoReflect() protoreflect.Message { + mi := &file_blockchain_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Proposal.ProtoReflect.Descriptor instead. +func (*Proposal) Descriptor() ([]byte, []int) { + return file_blockchain_proto_rawDescGZIP(), []int{27} +} + +func (x *Proposal) GetHeight() uint32 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *Proposal) GetRound() int32 { + if x != nil { + return x.Round + } + return 0 +} + +func (x *Proposal) GetBlockData() string { + if x != nil { + return x.BlockData + } + return "" +} + +func (x *Proposal) GetSignatureData() string { + if x != nil { + return x.SignatureData + } + return "" +} + var File_blockchain_proto protoreflect.FileDescriptor var file_blockchain_proto_rawDesc = []byte{ @@ -1942,167 +2027,178 @@ var file_blockchain_proto_rawDesc = []byte{ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4f, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7d, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x17, 0x47, 0x65, - 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x70, 0x61, - 0x63, 0x74, 0x75, 0x73, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x22, 0x45, 0x0a, - 0x18, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x74, 0x78, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x03, 0x74, 0x78, 0x73, 0x22, 0xdc, 0x02, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, - 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x6f, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, - 0x53, 0x6f, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, - 0x29, 0x0a, 0x10, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x75, 0x6e, 0x62, 0x6f, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x11, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, - 0x6f, 0x72, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xc4, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x70, 0x72, 0x65, 0x76, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1d, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0e, - 0x73, 0x6f, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x65, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x97, - 0x01, 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1e, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, - 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x09, - 0x61, 0x62, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, - 0x09, 0x61, 0x62, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x08, 0x56, 0x6f, 0x74, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x56, 0x6f, 0x74, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x6f, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x6f, 0x74, 0x65, - 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x70, 0x5f, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x70, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x97, 0x01, 0x0a, - 0x0d, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x08, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, + 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0x51, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, + 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x63, 0x74, + 0x75, 0x73, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x22, 0x45, 0x0a, 0x18, 0x47, + 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x74, 0x78, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x03, 0x74, + 0x78, 0x73, 0x22, 0xdc, 0x02, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x6f, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x6f, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x29, 0x0a, + 0x10, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x11, + 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, + 0x65, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xc4, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, + 0x65, 0x76, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x65, + 0x64, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x97, 0x01, 0x0a, + 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x68, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0a, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x62, + 0x73, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x09, 0x61, + 0x62, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x08, 0x56, 0x6f, 0x74, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x56, 0x6f, 0x74, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x6f, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x12, + 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, + 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x70, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x63, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x07, 0x63, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x0d, 0x43, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x26, 0x0a, 0x05, + 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x61, + 0x63, 0x74, 0x75, 0x73, 0x2e, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x76, + 0x6f, 0x74, 0x65, 0x73, 0x22, 0x7e, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, + 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x26, - 0x0a, 0x05, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x05, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x2a, 0x48, 0x0a, 0x0e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, - 0x65, 0x72, 0x62, 0x6f, 0x73, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x0a, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x02, - 0x2a, 0x5c, 0x0a, 0x08, 0x56, 0x6f, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, - 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, - 0x0a, 0x0c, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x01, - 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, - 0x49, 0x54, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x43, 0x48, 0x41, - 0x4e, 0x47, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x10, 0x03, 0x32, 0x8b, - 0x07, 0x0a, 0x0a, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, - 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x17, 0x2e, 0x70, 0x61, 0x63, 0x74, - 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x2e, 0x70, - 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, - 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, - 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x2e, 0x70, 0x61, 0x63, 0x74, - 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, - 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x2e, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, + 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x44, 0x61, 0x74, 0x61, 0x2a, 0x48, 0x0a, 0x0e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, + 0x62, 0x6f, 0x73, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x0a, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, + 0x44, 0x41, 0x54, 0x41, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, + 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, + 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x02, 0x2a, 0x5c, + 0x0a, 0x08, 0x56, 0x6f, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x56, 0x4f, + 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, + 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x01, 0x12, 0x12, + 0x0a, 0x0e, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, + 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, + 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x45, 0x52, 0x10, 0x03, 0x32, 0x8b, 0x07, 0x0a, + 0x0a, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x08, 0x47, + 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x17, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, + 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, + 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x2e, 0x70, 0x61, + 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, - 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1b, - 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, + 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, + 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x2e, 0x70, + 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, + 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, + 0x23, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, + 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x64, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x14, 0x47, 0x65, 0x74, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x12, 0x23, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, - 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x24, 0x2e, - 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, - 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, - 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, - 0x2e, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, - 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x70, 0x61, 0x63, 0x74, - 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x61, 0x63, - 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x45, 0x0a, 0x11, - 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, - 0x63, 0x74, 0x75, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x61, 0x63, - 0x74, 0x75, 0x73, 0x2f, 0x77, 0x77, 0x77, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x61, 0x63, - 0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x45, 0x0a, 0x11, 0x70, 0x61, + 0x63, 0x74, 0x75, 0x73, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5a, + 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x63, 0x74, + 0x75, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x61, 0x63, 0x74, 0x75, + 0x73, 0x2f, 0x77, 0x77, 0x77, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x61, 0x63, 0x74, 0x75, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2118,7 +2214,7 @@ func file_blockchain_proto_rawDescGZIP() []byte { } var file_blockchain_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_blockchain_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_blockchain_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_blockchain_proto_goTypes = []any{ (BlockVerbosity)(0), // 0: pactus.BlockVerbosity (VoteType)(0), // 1: pactus.VoteType @@ -2149,8 +2245,9 @@ var file_blockchain_proto_goTypes = []any{ (*CertificateInfo)(nil), // 26: pactus.CertificateInfo (*VoteInfo)(nil), // 27: pactus.VoteInfo (*ConsensusInfo)(nil), // 28: pactus.ConsensusInfo - (*TransactionInfo)(nil), // 29: pactus.TransactionInfo - (PayloadType)(0), // 30: pactus.PayloadType + (*Proposal)(nil), // 29: pactus.Proposal + (*TransactionInfo)(nil), // 30: pactus.TransactionInfo + (PayloadType)(0), // 31: pactus.PayloadType } var file_blockchain_proto_depIdxs = []int32{ 24, // 0: pactus.GetAccountResponse.account:type_name -> pactus.AccountInfo @@ -2158,40 +2255,41 @@ var file_blockchain_proto_depIdxs = []int32{ 0, // 2: pactus.GetBlockRequest.verbosity:type_name -> pactus.BlockVerbosity 25, // 3: pactus.GetBlockResponse.header:type_name -> pactus.BlockHeaderInfo 26, // 4: pactus.GetBlockResponse.prev_cert:type_name -> pactus.CertificateInfo - 29, // 5: pactus.GetBlockResponse.txs:type_name -> pactus.TransactionInfo + 30, // 5: pactus.GetBlockResponse.txs:type_name -> pactus.TransactionInfo 23, // 6: pactus.GetBlockchainInfoResponse.committee_validators:type_name -> pactus.ValidatorInfo 28, // 7: pactus.GetConsensusInfoResponse.instances:type_name -> pactus.ConsensusInfo - 30, // 8: pactus.GetTxPoolContentRequest.payload_type:type_name -> pactus.PayloadType - 29, // 9: pactus.GetTxPoolContentResponse.txs:type_name -> pactus.TransactionInfo - 1, // 10: pactus.VoteInfo.type:type_name -> pactus.VoteType - 27, // 11: pactus.ConsensusInfo.votes:type_name -> pactus.VoteInfo - 11, // 12: pactus.Blockchain.GetBlock:input_type -> pactus.GetBlockRequest - 13, // 13: pactus.Blockchain.GetBlockHash:input_type -> pactus.GetBlockHashRequest - 15, // 14: pactus.Blockchain.GetBlockHeight:input_type -> pactus.GetBlockHeightRequest - 17, // 15: pactus.Blockchain.GetBlockchainInfo:input_type -> pactus.GetBlockchainInfoRequest - 19, // 16: pactus.Blockchain.GetConsensusInfo:input_type -> pactus.GetConsensusInfoRequest - 2, // 17: pactus.Blockchain.GetAccount:input_type -> pactus.GetAccountRequest - 6, // 18: pactus.Blockchain.GetValidator:input_type -> pactus.GetValidatorRequest - 7, // 19: pactus.Blockchain.GetValidatorByNumber:input_type -> pactus.GetValidatorByNumberRequest - 4, // 20: pactus.Blockchain.GetValidatorAddresses:input_type -> pactus.GetValidatorAddressesRequest - 9, // 21: pactus.Blockchain.GetPublicKey:input_type -> pactus.GetPublicKeyRequest - 21, // 22: pactus.Blockchain.GetTxPoolContent:input_type -> pactus.GetTxPoolContentRequest - 12, // 23: pactus.Blockchain.GetBlock:output_type -> pactus.GetBlockResponse - 14, // 24: pactus.Blockchain.GetBlockHash:output_type -> pactus.GetBlockHashResponse - 16, // 25: pactus.Blockchain.GetBlockHeight:output_type -> pactus.GetBlockHeightResponse - 18, // 26: pactus.Blockchain.GetBlockchainInfo:output_type -> pactus.GetBlockchainInfoResponse - 20, // 27: pactus.Blockchain.GetConsensusInfo:output_type -> pactus.GetConsensusInfoResponse - 3, // 28: pactus.Blockchain.GetAccount:output_type -> pactus.GetAccountResponse - 8, // 29: pactus.Blockchain.GetValidator:output_type -> pactus.GetValidatorResponse - 8, // 30: pactus.Blockchain.GetValidatorByNumber:output_type -> pactus.GetValidatorResponse - 5, // 31: pactus.Blockchain.GetValidatorAddresses:output_type -> pactus.GetValidatorAddressesResponse - 10, // 32: pactus.Blockchain.GetPublicKey:output_type -> pactus.GetPublicKeyResponse - 22, // 33: pactus.Blockchain.GetTxPoolContent:output_type -> pactus.GetTxPoolContentResponse - 23, // [23:34] is the sub-list for method output_type - 12, // [12:23] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 29, // 8: pactus.GetConsensusInfoResponse.proposal:type_name -> pactus.Proposal + 31, // 9: pactus.GetTxPoolContentRequest.payload_type:type_name -> pactus.PayloadType + 30, // 10: pactus.GetTxPoolContentResponse.txs:type_name -> pactus.TransactionInfo + 1, // 11: pactus.VoteInfo.type:type_name -> pactus.VoteType + 27, // 12: pactus.ConsensusInfo.votes:type_name -> pactus.VoteInfo + 11, // 13: pactus.Blockchain.GetBlock:input_type -> pactus.GetBlockRequest + 13, // 14: pactus.Blockchain.GetBlockHash:input_type -> pactus.GetBlockHashRequest + 15, // 15: pactus.Blockchain.GetBlockHeight:input_type -> pactus.GetBlockHeightRequest + 17, // 16: pactus.Blockchain.GetBlockchainInfo:input_type -> pactus.GetBlockchainInfoRequest + 19, // 17: pactus.Blockchain.GetConsensusInfo:input_type -> pactus.GetConsensusInfoRequest + 2, // 18: pactus.Blockchain.GetAccount:input_type -> pactus.GetAccountRequest + 6, // 19: pactus.Blockchain.GetValidator:input_type -> pactus.GetValidatorRequest + 7, // 20: pactus.Blockchain.GetValidatorByNumber:input_type -> pactus.GetValidatorByNumberRequest + 4, // 21: pactus.Blockchain.GetValidatorAddresses:input_type -> pactus.GetValidatorAddressesRequest + 9, // 22: pactus.Blockchain.GetPublicKey:input_type -> pactus.GetPublicKeyRequest + 21, // 23: pactus.Blockchain.GetTxPoolContent:input_type -> pactus.GetTxPoolContentRequest + 12, // 24: pactus.Blockchain.GetBlock:output_type -> pactus.GetBlockResponse + 14, // 25: pactus.Blockchain.GetBlockHash:output_type -> pactus.GetBlockHashResponse + 16, // 26: pactus.Blockchain.GetBlockHeight:output_type -> pactus.GetBlockHeightResponse + 18, // 27: pactus.Blockchain.GetBlockchainInfo:output_type -> pactus.GetBlockchainInfoResponse + 20, // 28: pactus.Blockchain.GetConsensusInfo:output_type -> pactus.GetConsensusInfoResponse + 3, // 29: pactus.Blockchain.GetAccount:output_type -> pactus.GetAccountResponse + 8, // 30: pactus.Blockchain.GetValidator:output_type -> pactus.GetValidatorResponse + 8, // 31: pactus.Blockchain.GetValidatorByNumber:output_type -> pactus.GetValidatorResponse + 5, // 32: pactus.Blockchain.GetValidatorAddresses:output_type -> pactus.GetValidatorAddressesResponse + 10, // 33: pactus.Blockchain.GetPublicKey:output_type -> pactus.GetPublicKeyResponse + 22, // 34: pactus.Blockchain.GetTxPoolContent:output_type -> pactus.GetTxPoolContentResponse + 24, // [24:35] is the sub-list for method output_type + 13, // [13:24] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_blockchain_proto_init() } @@ -2525,6 +2623,18 @@ func file_blockchain_proto_init() { return nil } } + file_blockchain_proto_msgTypes[27].Exporter = func(v any, i int) any { + switch v := v.(*Proposal); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -2532,7 +2642,7 @@ func file_blockchain_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_blockchain_proto_rawDesc, NumEnums: 2, - NumMessages: 27, + NumMessages: 28, NumExtensions: 0, NumServices: 1, }, diff --git a/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java b/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java index efb543008..3241713b1 100644 --- a/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java +++ b/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java @@ -13094,6 +13094,33 @@ public interface GetConsensusInfoResponseOrBuilder extends */ pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( int index); + + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * @return Whether the proposal field is set. + */ + boolean hasProposal(); + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * @return The proposal. + */ + pactus.blockchain.BlockchainOuterClass.Proposal getProposal(); + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder(); } /** *
      @@ -13200,6 +13227,44 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstance
             return instances_.get(index);
           }
       
      +    public static final int PROPOSAL_FIELD_NUMBER = 6;
      +    private pactus.blockchain.BlockchainOuterClass.Proposal proposal_;
      +    /**
      +     * 
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * @return Whether the proposal field is set. + */ + @java.lang.Override + public boolean hasProposal() { + return proposal_ != null; + } + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * @return The proposal. + */ + @java.lang.Override + public pactus.blockchain.BlockchainOuterClass.Proposal getProposal() { + return proposal_ == null ? pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; + } + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + @java.lang.Override + public pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder() { + return getProposal(); + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -13217,6 +13282,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) for (int i = 0; i < instances_.size(); i++) { output.writeMessage(1, instances_.get(i)); } + if (proposal_ != null) { + output.writeMessage(6, getProposal()); + } getUnknownFields().writeTo(output); } @@ -13230,6 +13298,10 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(1, instances_.get(i)); } + if (proposal_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getProposal()); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -13247,6 +13319,11 @@ public boolean equals(final java.lang.Object obj) { if (!getInstancesList() .equals(other.getInstancesList())) return false; + if (hasProposal() != other.hasProposal()) return false; + if (hasProposal()) { + if (!getProposal() + .equals(other.getProposal())) return false; + } if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -13262,6 +13339,10 @@ public int hashCode() { hash = (37 * hash) + INSTANCES_FIELD_NUMBER; hash = (53 * hash) + getInstancesList().hashCode(); } + if (hasProposal()) { + hash = (37 * hash) + PROPOSAL_FIELD_NUMBER; + hash = (53 * hash) + getProposal().hashCode(); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -13401,6 +13482,12 @@ public Builder clear() { instancesBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000001); + if (proposalBuilder_ == null) { + proposal_ = null; + } else { + proposal_ = null; + proposalBuilder_ = null; + } return this; } @@ -13437,6 +13524,11 @@ public pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse buildPart } else { result.instances_ = instancesBuilder_.build(); } + if (proposalBuilder_ == null) { + result.proposal_ = proposal_; + } else { + result.proposal_ = proposalBuilder_.build(); + } onBuilt(); return result; } @@ -13511,6 +13603,9 @@ public Builder mergeFrom(pactus.blockchain.BlockchainOuterClass.GetConsensusInfo } } } + if (other.hasProposal()) { + mergeProposal(other.getProposal()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -13550,6 +13645,13 @@ public Builder mergeFrom( } break; } // case 10 + case 50: { + input.readMessage( + getProposalFieldBuilder().getBuilder(), + extensionRegistry); + + break; + } // case 50 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -13878,6 +13980,161 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder addInstances } return instancesBuilder_; } + + private pactus.blockchain.BlockchainOuterClass.Proposal proposal_; + private com.google.protobuf.SingleFieldBuilderV3< + pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder> proposalBuilder_; + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * @return Whether the proposal field is set. + */ + public boolean hasProposal() { + return proposalBuilder_ != null || proposal_ != null; + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * @return The proposal. + */ + public pactus.blockchain.BlockchainOuterClass.Proposal getProposal() { + if (proposalBuilder_ == null) { + return proposal_ == null ? pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; + } else { + return proposalBuilder_.getMessage(); + } + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + public Builder setProposal(pactus.blockchain.BlockchainOuterClass.Proposal value) { + if (proposalBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + proposal_ = value; + onChanged(); + } else { + proposalBuilder_.setMessage(value); + } + + return this; + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + public Builder setProposal( + pactus.blockchain.BlockchainOuterClass.Proposal.Builder builderForValue) { + if (proposalBuilder_ == null) { + proposal_ = builderForValue.build(); + onChanged(); + } else { + proposalBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + public Builder mergeProposal(pactus.blockchain.BlockchainOuterClass.Proposal value) { + if (proposalBuilder_ == null) { + if (proposal_ != null) { + proposal_ = + pactus.blockchain.BlockchainOuterClass.Proposal.newBuilder(proposal_).mergeFrom(value).buildPartial(); + } else { + proposal_ = value; + } + onChanged(); + } else { + proposalBuilder_.mergeFrom(value); + } + + return this; + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + public Builder clearProposal() { + if (proposalBuilder_ == null) { + proposal_ = null; + onChanged(); + } else { + proposal_ = null; + proposalBuilder_ = null; + } + + return this; + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + public pactus.blockchain.BlockchainOuterClass.Proposal.Builder getProposalBuilder() { + + onChanged(); + return getProposalFieldBuilder().getBuilder(); + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + public pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder() { + if (proposalBuilder_ != null) { + return proposalBuilder_.getMessageOrBuilder(); + } else { + return proposal_ == null ? + pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; + } + } + /** + *
      +       * The proposal of the consensus info.
      +       * 
      + * + * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + */ + private com.google.protobuf.SingleFieldBuilderV3< + pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder> + getProposalFieldBuilder() { + if (proposalBuilder_ == null) { + proposalBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder>( + getProposal(), + getParentForChildren(), + isClean()); + proposal_ = null; + } + return proposalBuilder_; + } @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -23360,117 +23617,1075 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getDefaultInstanceFo } - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetAccountRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetAccountRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetAccountResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetAccountResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetValidatorAddressesRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetValidatorAddressesRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetValidatorAddressesResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetValidatorAddressesResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetValidatorRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetValidatorRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetValidatorByNumberRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetValidatorByNumberRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetValidatorResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetValidatorResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetPublicKeyRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetPublicKeyRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetPublicKeyResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetPublicKeyResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockHashRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockHashRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockHashResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockHashResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockHeightRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockHeightRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockHeightResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockHeightResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockchainInfoRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockchainInfoRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetBlockchainInfoResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetBlockchainInfoResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetConsensusInfoRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetConsensusInfoRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetConsensusInfoResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetConsensusInfoResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetTxPoolContentRequest_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetTxPoolContentRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_GetTxPoolContentResponse_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_GetTxPoolContentResponse_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_pactus_ValidatorInfo_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_pactus_ValidatorInfo_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor + public interface ProposalOrBuilder extends + // @@protoc_insertion_point(interface_extends:pactus.Proposal) + com.google.protobuf.MessageOrBuilder { + + /** + *
      +     * The height of the proposal.
      +     * 
      + * + * uint32 height = 1 [json_name = "height"]; + * @return The height. + */ + int getHeight(); + + /** + *
      +     * The round of the proposal.
      +     * 
      + * + * int32 round = 2 [json_name = "round"]; + * @return The round. + */ + int getRound(); + + /** + *
      +     * The block data of the proposal.
      +     * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return The blockData. + */ + java.lang.String getBlockData(); + /** + *
      +     * The block data of the proposal.
      +     * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return The bytes for blockData. + */ + com.google.protobuf.ByteString + getBlockDataBytes(); + + /** + *
      +     * The signature data of the proposal.
      +     * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return The signatureData. + */ + java.lang.String getSignatureData(); + /** + *
      +     * The signature data of the proposal.
      +     * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return The bytes for signatureData. + */ + com.google.protobuf.ByteString + getSignatureDataBytes(); + } + /** + *
      +   * Message containing information about a proposal.
      +   * 
      + * + * Protobuf type {@code pactus.Proposal} + */ + public static final class Proposal extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:pactus.Proposal) + ProposalOrBuilder { + private static final long serialVersionUID = 0L; + // Use Proposal.newBuilder() to construct. + private Proposal(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Proposal() { + blockData_ = ""; + signatureData_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Proposal(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return pactus.blockchain.BlockchainOuterClass.internal_static_pactus_Proposal_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return pactus.blockchain.BlockchainOuterClass.internal_static_pactus_Proposal_fieldAccessorTable + .ensureFieldAccessorsInitialized( + pactus.blockchain.BlockchainOuterClass.Proposal.class, pactus.blockchain.BlockchainOuterClass.Proposal.Builder.class); + } + + public static final int HEIGHT_FIELD_NUMBER = 1; + private int height_; + /** + *
      +     * The height of the proposal.
      +     * 
      + * + * uint32 height = 1 [json_name = "height"]; + * @return The height. + */ + @java.lang.Override + public int getHeight() { + return height_; + } + + public static final int ROUND_FIELD_NUMBER = 2; + private int round_; + /** + *
      +     * The round of the proposal.
      +     * 
      + * + * int32 round = 2 [json_name = "round"]; + * @return The round. + */ + @java.lang.Override + public int getRound() { + return round_; + } + + public static final int BLOCK_DATA_FIELD_NUMBER = 3; + private volatile java.lang.Object blockData_; + /** + *
      +     * The block data of the proposal.
      +     * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return The blockData. + */ + @java.lang.Override + public java.lang.String getBlockData() { + java.lang.Object ref = blockData_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + blockData_ = s; + return s; + } + } + /** + *
      +     * The block data of the proposal.
      +     * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return The bytes for blockData. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getBlockDataBytes() { + java.lang.Object ref = blockData_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + blockData_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SIGNATURE_DATA_FIELD_NUMBER = 4; + private volatile java.lang.Object signatureData_; + /** + *
      +     * The signature data of the proposal.
      +     * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return The signatureData. + */ + @java.lang.Override + public java.lang.String getSignatureData() { + java.lang.Object ref = signatureData_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + signatureData_ = s; + return s; + } + } + /** + *
      +     * The signature data of the proposal.
      +     * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return The bytes for signatureData. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getSignatureDataBytes() { + java.lang.Object ref = signatureData_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + signatureData_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (height_ != 0) { + output.writeUInt32(1, height_); + } + if (round_ != 0) { + output.writeInt32(2, round_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(blockData_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, blockData_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(signatureData_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, signatureData_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (height_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, height_); + } + if (round_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, round_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(blockData_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, blockData_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(signatureData_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, signatureData_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof pactus.blockchain.BlockchainOuterClass.Proposal)) { + return super.equals(obj); + } + pactus.blockchain.BlockchainOuterClass.Proposal other = (pactus.blockchain.BlockchainOuterClass.Proposal) obj; + + if (getHeight() + != other.getHeight()) return false; + if (getRound() + != other.getRound()) return false; + if (!getBlockData() + .equals(other.getBlockData())) return false; + if (!getSignatureData() + .equals(other.getSignatureData())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + HEIGHT_FIELD_NUMBER; + hash = (53 * hash) + getHeight(); + hash = (37 * hash) + ROUND_FIELD_NUMBER; + hash = (53 * hash) + getRound(); + hash = (37 * hash) + BLOCK_DATA_FIELD_NUMBER; + hash = (53 * hash) + getBlockData().hashCode(); + hash = (37 * hash) + SIGNATURE_DATA_FIELD_NUMBER; + hash = (53 * hash) + getSignatureData().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static pactus.blockchain.BlockchainOuterClass.Proposal parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(pactus.blockchain.BlockchainOuterClass.Proposal prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
      +     * Message containing information about a proposal.
      +     * 
      + * + * Protobuf type {@code pactus.Proposal} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:pactus.Proposal) + pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return pactus.blockchain.BlockchainOuterClass.internal_static_pactus_Proposal_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return pactus.blockchain.BlockchainOuterClass.internal_static_pactus_Proposal_fieldAccessorTable + .ensureFieldAccessorsInitialized( + pactus.blockchain.BlockchainOuterClass.Proposal.class, pactus.blockchain.BlockchainOuterClass.Proposal.Builder.class); + } + + // Construct using pactus.blockchain.BlockchainOuterClass.Proposal.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + height_ = 0; + + round_ = 0; + + blockData_ = ""; + + signatureData_ = ""; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return pactus.blockchain.BlockchainOuterClass.internal_static_pactus_Proposal_descriptor; + } + + @java.lang.Override + public pactus.blockchain.BlockchainOuterClass.Proposal getDefaultInstanceForType() { + return pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance(); + } + + @java.lang.Override + public pactus.blockchain.BlockchainOuterClass.Proposal build() { + pactus.blockchain.BlockchainOuterClass.Proposal result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public pactus.blockchain.BlockchainOuterClass.Proposal buildPartial() { + pactus.blockchain.BlockchainOuterClass.Proposal result = new pactus.blockchain.BlockchainOuterClass.Proposal(this); + result.height_ = height_; + result.round_ = round_; + result.blockData_ = blockData_; + result.signatureData_ = signatureData_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof pactus.blockchain.BlockchainOuterClass.Proposal) { + return mergeFrom((pactus.blockchain.BlockchainOuterClass.Proposal)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(pactus.blockchain.BlockchainOuterClass.Proposal other) { + if (other == pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance()) return this; + if (other.getHeight() != 0) { + setHeight(other.getHeight()); + } + if (other.getRound() != 0) { + setRound(other.getRound()); + } + if (!other.getBlockData().isEmpty()) { + blockData_ = other.blockData_; + onChanged(); + } + if (!other.getSignatureData().isEmpty()) { + signatureData_ = other.signatureData_; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + height_ = input.readUInt32(); + + break; + } // case 8 + case 16: { + round_ = input.readInt32(); + + break; + } // case 16 + case 26: { + blockData_ = input.readStringRequireUtf8(); + + break; + } // case 26 + case 34: { + signatureData_ = input.readStringRequireUtf8(); + + break; + } // case 34 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + private int height_ ; + /** + *
      +       * The height of the proposal.
      +       * 
      + * + * uint32 height = 1 [json_name = "height"]; + * @return The height. + */ + @java.lang.Override + public int getHeight() { + return height_; + } + /** + *
      +       * The height of the proposal.
      +       * 
      + * + * uint32 height = 1 [json_name = "height"]; + * @param value The height to set. + * @return This builder for chaining. + */ + public Builder setHeight(int value) { + + height_ = value; + onChanged(); + return this; + } + /** + *
      +       * The height of the proposal.
      +       * 
      + * + * uint32 height = 1 [json_name = "height"]; + * @return This builder for chaining. + */ + public Builder clearHeight() { + + height_ = 0; + onChanged(); + return this; + } + + private int round_ ; + /** + *
      +       * The round of the proposal.
      +       * 
      + * + * int32 round = 2 [json_name = "round"]; + * @return The round. + */ + @java.lang.Override + public int getRound() { + return round_; + } + /** + *
      +       * The round of the proposal.
      +       * 
      + * + * int32 round = 2 [json_name = "round"]; + * @param value The round to set. + * @return This builder for chaining. + */ + public Builder setRound(int value) { + + round_ = value; + onChanged(); + return this; + } + /** + *
      +       * The round of the proposal.
      +       * 
      + * + * int32 round = 2 [json_name = "round"]; + * @return This builder for chaining. + */ + public Builder clearRound() { + + round_ = 0; + onChanged(); + return this; + } + + private java.lang.Object blockData_ = ""; + /** + *
      +       * The block data of the proposal.
      +       * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return The blockData. + */ + public java.lang.String getBlockData() { + java.lang.Object ref = blockData_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + blockData_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
      +       * The block data of the proposal.
      +       * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return The bytes for blockData. + */ + public com.google.protobuf.ByteString + getBlockDataBytes() { + java.lang.Object ref = blockData_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + blockData_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
      +       * The block data of the proposal.
      +       * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @param value The blockData to set. + * @return This builder for chaining. + */ + public Builder setBlockData( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + blockData_ = value; + onChanged(); + return this; + } + /** + *
      +       * The block data of the proposal.
      +       * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @return This builder for chaining. + */ + public Builder clearBlockData() { + + blockData_ = getDefaultInstance().getBlockData(); + onChanged(); + return this; + } + /** + *
      +       * The block data of the proposal.
      +       * 
      + * + * string block_data = 3 [json_name = "blockData"]; + * @param value The bytes for blockData to set. + * @return This builder for chaining. + */ + public Builder setBlockDataBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + blockData_ = value; + onChanged(); + return this; + } + + private java.lang.Object signatureData_ = ""; + /** + *
      +       * The signature data of the proposal.
      +       * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return The signatureData. + */ + public java.lang.String getSignatureData() { + java.lang.Object ref = signatureData_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + signatureData_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
      +       * The signature data of the proposal.
      +       * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return The bytes for signatureData. + */ + public com.google.protobuf.ByteString + getSignatureDataBytes() { + java.lang.Object ref = signatureData_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + signatureData_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
      +       * The signature data of the proposal.
      +       * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @param value The signatureData to set. + * @return This builder for chaining. + */ + public Builder setSignatureData( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + signatureData_ = value; + onChanged(); + return this; + } + /** + *
      +       * The signature data of the proposal.
      +       * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @return This builder for chaining. + */ + public Builder clearSignatureData() { + + signatureData_ = getDefaultInstance().getSignatureData(); + onChanged(); + return this; + } + /** + *
      +       * The signature data of the proposal.
      +       * 
      + * + * string signature_data = 4 [json_name = "signatureData"]; + * @param value The bytes for signatureData to set. + * @return This builder for chaining. + */ + public Builder setSignatureDataBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + signatureData_ = value; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:pactus.Proposal) + } + + // @@protoc_insertion_point(class_scope:pactus.Proposal) + private static final pactus.blockchain.BlockchainOuterClass.Proposal DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new pactus.blockchain.BlockchainOuterClass.Proposal(); + } + + public static pactus.blockchain.BlockchainOuterClass.Proposal getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Proposal parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public pactus.blockchain.BlockchainOuterClass.Proposal getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetAccountRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetAccountRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetAccountResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetAccountResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetValidatorAddressesRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetValidatorAddressesRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetValidatorAddressesResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetValidatorAddressesResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetValidatorRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetValidatorRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetValidatorByNumberRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetValidatorByNumberRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetValidatorResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetValidatorResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetPublicKeyRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetPublicKeyRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetPublicKeyResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetPublicKeyResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockHashRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockHashRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockHashResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockHashResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockHeightRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockHeightRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockHeightResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockHeightResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockchainInfoRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockchainInfoRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetBlockchainInfoResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetBlockchainInfoResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetConsensusInfoRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetConsensusInfoRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetConsensusInfoResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetConsensusInfoResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetTxPoolContentRequest_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetTxPoolContentRequest_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_GetTxPoolContentResponse_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_GetTxPoolContentResponse_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_ValidatorInfo_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_ValidatorInfo_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor internal_static_pactus_AccountInfo_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable @@ -23495,6 +24710,11 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getDefaultInstanceFo private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_pactus_ConsensusInfo_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_pactus_Proposal_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_pactus_Proposal_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -23543,71 +24763,76 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getDefaultInstanceFo "ommitteeValidators\022\033\n\tis_pruned\030\010 \001(\010R\010i" + "sPruned\022%\n\016pruning_height\030\t \001(\rR\rpruning" + "Height\022&\n\017last_block_time\030\n \001(\003R\rlastBlo" + - "ckTime\"\031\n\027GetConsensusInfoRequest\"O\n\030Get" + + "ckTime\"\031\n\027GetConsensusInfoRequest\"}\n\030Get" + "ConsensusInfoResponse\0223\n\tinstances\030\001 \003(\013" + - "2\025.pactus.ConsensusInfoR\tinstances\"Q\n\027Ge" + - "tTxPoolContentRequest\0226\n\014payload_type\030\001 " + - "\001(\0162\023.pactus.PayloadTypeR\013payloadType\"E\n" + - "\030GetTxPoolContentResponse\022)\n\003txs\030\001 \003(\0132\027" + - ".pactus.TransactionInfoR\003txs\"\334\002\n\rValidat" + - "orInfo\022\022\n\004hash\030\001 \001(\tR\004hash\022\022\n\004data\030\002 \001(\t" + - "R\004data\022\035\n\npublic_key\030\003 \001(\tR\tpublicKey\022\026\n" + - "\006number\030\004 \001(\005R\006number\022\024\n\005stake\030\005 \001(\003R\005st" + - "ake\022.\n\023last_bonding_height\030\006 \001(\rR\021lastBo" + - "ndingHeight\0222\n\025last_sortition_height\030\007 \001" + - "(\rR\023lastSortitionHeight\022)\n\020unbonding_hei" + - "ght\030\010 \001(\rR\017unbondingHeight\022\030\n\007address\030\t " + - "\001(\tR\007address\022-\n\022availability_score\030\n \001(\001" + - "R\021availabilityScore\"\201\001\n\013AccountInfo\022\022\n\004h" + - "ash\030\001 \001(\tR\004hash\022\022\n\004data\030\002 \001(\tR\004data\022\026\n\006n" + - "umber\030\003 \001(\005R\006number\022\030\n\007balance\030\004 \001(\003R\007ba" + - "lance\022\030\n\007address\030\005 \001(\tR\007address\"\304\001\n\017Bloc" + - "kHeaderInfo\022\030\n\007version\030\001 \001(\005R\007version\022&\n" + - "\017prev_block_hash\030\002 \001(\tR\rprevBlockHash\022\035\n" + - "\nstate_root\030\003 \001(\tR\tstateRoot\022%\n\016sortitio" + - "n_seed\030\004 \001(\tR\rsortitionSeed\022)\n\020proposer_" + - "address\030\005 \001(\tR\017proposerAddress\"\227\001\n\017Certi" + - "ficateInfo\022\022\n\004hash\030\001 \001(\tR\004hash\022\024\n\005round\030" + - "\002 \001(\005R\005round\022\036\n\ncommitters\030\003 \003(\005R\ncommit" + - "ters\022\034\n\tabsentees\030\004 \003(\005R\tabsentees\022\034\n\tsi" + - "gnature\030\005 \001(\tR\tsignature\"\261\001\n\010VoteInfo\022$\n" + - "\004type\030\001 \001(\0162\020.pactus.VoteTypeR\004type\022\024\n\005v" + - "oter\030\002 \001(\tR\005voter\022\035\n\nblock_hash\030\003 \001(\tR\tb" + - "lockHash\022\024\n\005round\030\004 \001(\005R\005round\022\031\n\010cp_rou" + - "nd\030\005 \001(\005R\007cpRound\022\031\n\010cp_value\030\006 \001(\005R\007cpV" + - "alue\"\227\001\n\rConsensusInfo\022\030\n\007address\030\001 \001(\tR" + - "\007address\022\026\n\006active\030\002 \001(\010R\006active\022\026\n\006heig" + - "ht\030\003 \001(\rR\006height\022\024\n\005round\030\004 \001(\005R\005round\022&" + - "\n\005votes\030\005 \003(\0132\020.pactus.VoteInfoR\005votes*H" + - "\n\016BlockVerbosity\022\016\n\nBLOCK_DATA\020\000\022\016\n\nBLOC" + - "K_INFO\020\001\022\026\n\022BLOCK_TRANSACTIONS\020\002*\\\n\010Vote" + - "Type\022\020\n\014VOTE_UNKNOWN\020\000\022\020\n\014VOTE_PREPARE\020\001" + - "\022\022\n\016VOTE_PRECOMMIT\020\002\022\030\n\024VOTE_CHANGE_PROP" + - "OSER\020\0032\213\007\n\nBlockchain\022=\n\010GetBlock\022\027.pact" + - "us.GetBlockRequest\032\030.pactus.GetBlockResp" + - "onse\022I\n\014GetBlockHash\022\033.pactus.GetBlockHa" + - "shRequest\032\034.pactus.GetBlockHashResponse\022" + - "O\n\016GetBlockHeight\022\035.pactus.GetBlockHeigh" + - "tRequest\032\036.pactus.GetBlockHeightResponse" + - "\022X\n\021GetBlockchainInfo\022 .pactus.GetBlockc" + - "hainInfoRequest\032!.pactus.GetBlockchainIn" + - "foResponse\022U\n\020GetConsensusInfo\022\037.pactus." + - "GetConsensusInfoRequest\032 .pactus.GetCons" + - "ensusInfoResponse\022C\n\nGetAccount\022\031.pactus" + - ".GetAccountRequest\032\032.pactus.GetAccountRe" + - "sponse\022I\n\014GetValidator\022\033.pactus.GetValid" + - "atorRequest\032\034.pactus.GetValidatorRespons" + - "e\022Y\n\024GetValidatorByNumber\022#.pactus.GetVa" + - "lidatorByNumberRequest\032\034.pactus.GetValid" + - "atorResponse\022d\n\025GetValidatorAddresses\022$." + - "pactus.GetValidatorAddressesRequest\032%.pa" + - "ctus.GetValidatorAddressesResponse\022I\n\014Ge" + - "tPublicKey\022\033.pactus.GetPublicKeyRequest\032" + - "\034.pactus.GetPublicKeyResponse\022U\n\020GetTxPo" + - "olContent\022\037.pactus.GetTxPoolContentReque" + - "st\032 .pactus.GetTxPoolContentResponseBE\n\021" + - "pactus.blockchainZ0github.com/pactus-pro" + - "ject/pactus/www/grpc/pactusb\006proto3" + "2\025.pactus.ConsensusInfoR\tinstances\022,\n\010pr" + + "oposal\030\006 \001(\0132\020.pactus.ProposalR\010proposal" + + "\"Q\n\027GetTxPoolContentRequest\0226\n\014payload_t" + + "ype\030\001 \001(\0162\023.pactus.PayloadTypeR\013payloadT" + + "ype\"E\n\030GetTxPoolContentResponse\022)\n\003txs\030\001" + + " \003(\0132\027.pactus.TransactionInfoR\003txs\"\334\002\n\rV" + + "alidatorInfo\022\022\n\004hash\030\001 \001(\tR\004hash\022\022\n\004data" + + "\030\002 \001(\tR\004data\022\035\n\npublic_key\030\003 \001(\tR\tpublic" + + "Key\022\026\n\006number\030\004 \001(\005R\006number\022\024\n\005stake\030\005 \001" + + "(\003R\005stake\022.\n\023last_bonding_height\030\006 \001(\rR\021" + + "lastBondingHeight\0222\n\025last_sortition_heig" + + "ht\030\007 \001(\rR\023lastSortitionHeight\022)\n\020unbondi" + + "ng_height\030\010 \001(\rR\017unbondingHeight\022\030\n\007addr" + + "ess\030\t \001(\tR\007address\022-\n\022availability_score" + + "\030\n \001(\001R\021availabilityScore\"\201\001\n\013AccountInf" + + "o\022\022\n\004hash\030\001 \001(\tR\004hash\022\022\n\004data\030\002 \001(\tR\004dat" + + "a\022\026\n\006number\030\003 \001(\005R\006number\022\030\n\007balance\030\004 \001" + + "(\003R\007balance\022\030\n\007address\030\005 \001(\tR\007address\"\304\001" + + "\n\017BlockHeaderInfo\022\030\n\007version\030\001 \001(\005R\007vers" + + "ion\022&\n\017prev_block_hash\030\002 \001(\tR\rprevBlockH" + + "ash\022\035\n\nstate_root\030\003 \001(\tR\tstateRoot\022%\n\016so" + + "rtition_seed\030\004 \001(\tR\rsortitionSeed\022)\n\020pro" + + "poser_address\030\005 \001(\tR\017proposerAddress\"\227\001\n" + + "\017CertificateInfo\022\022\n\004hash\030\001 \001(\tR\004hash\022\024\n\005" + + "round\030\002 \001(\005R\005round\022\036\n\ncommitters\030\003 \003(\005R\n" + + "committers\022\034\n\tabsentees\030\004 \003(\005R\tabsentees" + + "\022\034\n\tsignature\030\005 \001(\tR\tsignature\"\261\001\n\010VoteI" + + "nfo\022$\n\004type\030\001 \001(\0162\020.pactus.VoteTypeR\004typ" + + "e\022\024\n\005voter\030\002 \001(\tR\005voter\022\035\n\nblock_hash\030\003 " + + "\001(\tR\tblockHash\022\024\n\005round\030\004 \001(\005R\005round\022\031\n\010" + + "cp_round\030\005 \001(\005R\007cpRound\022\031\n\010cp_value\030\006 \001(" + + "\005R\007cpValue\"\227\001\n\rConsensusInfo\022\030\n\007address\030" + + "\001 \001(\tR\007address\022\026\n\006active\030\002 \001(\010R\006active\022\026" + + "\n\006height\030\003 \001(\rR\006height\022\024\n\005round\030\004 \001(\005R\005r" + + "ound\022&\n\005votes\030\005 \003(\0132\020.pactus.VoteInfoR\005v" + + "otes\"~\n\010Proposal\022\026\n\006height\030\001 \001(\rR\006height" + + "\022\024\n\005round\030\002 \001(\005R\005round\022\035\n\nblock_data\030\003 \001" + + "(\tR\tblockData\022%\n\016signature_data\030\004 \001(\tR\rs" + + "ignatureData*H\n\016BlockVerbosity\022\016\n\nBLOCK_" + + "DATA\020\000\022\016\n\nBLOCK_INFO\020\001\022\026\n\022BLOCK_TRANSACT" + + "IONS\020\002*\\\n\010VoteType\022\020\n\014VOTE_UNKNOWN\020\000\022\020\n\014" + + "VOTE_PREPARE\020\001\022\022\n\016VOTE_PRECOMMIT\020\002\022\030\n\024VO" + + "TE_CHANGE_PROPOSER\020\0032\213\007\n\nBlockchain\022=\n\010G" + + "etBlock\022\027.pactus.GetBlockRequest\032\030.pactu" + + "s.GetBlockResponse\022I\n\014GetBlockHash\022\033.pac" + + "tus.GetBlockHashRequest\032\034.pactus.GetBloc" + + "kHashResponse\022O\n\016GetBlockHeight\022\035.pactus" + + ".GetBlockHeightRequest\032\036.pactus.GetBlock" + + "HeightResponse\022X\n\021GetBlockchainInfo\022 .pa" + + "ctus.GetBlockchainInfoRequest\032!.pactus.G" + + "etBlockchainInfoResponse\022U\n\020GetConsensus" + + "Info\022\037.pactus.GetConsensusInfoRequest\032 ." + + "pactus.GetConsensusInfoResponse\022C\n\nGetAc" + + "count\022\031.pactus.GetAccountRequest\032\032.pactu" + + "s.GetAccountResponse\022I\n\014GetValidator\022\033.p" + + "actus.GetValidatorRequest\032\034.pactus.GetVa" + + "lidatorResponse\022Y\n\024GetValidatorByNumber\022" + + "#.pactus.GetValidatorByNumberRequest\032\034.p" + + "actus.GetValidatorResponse\022d\n\025GetValidat" + + "orAddresses\022$.pactus.GetValidatorAddress" + + "esRequest\032%.pactus.GetValidatorAddresses" + + "Response\022I\n\014GetPublicKey\022\033.pactus.GetPub" + + "licKeyRequest\032\034.pactus.GetPublicKeyRespo" + + "nse\022U\n\020GetTxPoolContent\022\037.pactus.GetTxPo" + + "olContentRequest\032 .pactus.GetTxPoolConte" + + "ntResponseBE\n\021pactus.blockchainZ0github." + + "com/pactus-project/pactus/www/grpc/pactu" + + "sb\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -23727,7 +24952,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getDefaultInstanceFo internal_static_pactus_GetConsensusInfoResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_pactus_GetConsensusInfoResponse_descriptor, - new java.lang.String[] { "Instances", }); + new java.lang.String[] { "Instances", "Proposal", }); internal_static_pactus_GetTxPoolContentRequest_descriptor = getDescriptor().getMessageTypes().get(19); internal_static_pactus_GetTxPoolContentRequest_fieldAccessorTable = new @@ -23776,6 +25001,12 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getDefaultInstanceFo com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_pactus_ConsensusInfo_descriptor, new java.lang.String[] { "Address", "Active", "Height", "Round", "Votes", }); + internal_static_pactus_Proposal_descriptor = + getDescriptor().getMessageTypes().get(27); + internal_static_pactus_Proposal_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_pactus_Proposal_descriptor, + new java.lang.String[] { "Height", "Round", "BlockData", "SignatureData", }); pactus.transaction.TransactionOuterClass.getDescriptor(); } diff --git a/www/grpc/gen/js/blockchain_pb.js b/www/grpc/gen/js/blockchain_pb.js index b763cfa55..e9f2d347e 100644 --- a/www/grpc/gen/js/blockchain_pb.js +++ b/www/grpc/gen/js/blockchain_pb.js @@ -49,6 +49,7 @@ goog.exportSymbol('proto.pactus.GetValidatorAddressesResponse', null, global); goog.exportSymbol('proto.pactus.GetValidatorByNumberRequest', null, global); goog.exportSymbol('proto.pactus.GetValidatorRequest', null, global); goog.exportSymbol('proto.pactus.GetValidatorResponse', null, global); +goog.exportSymbol('proto.pactus.Proposal', null, global); goog.exportSymbol('proto.pactus.ValidatorInfo', null, global); goog.exportSymbol('proto.pactus.VoteInfo', null, global); goog.exportSymbol('proto.pactus.VoteType', null, global); @@ -619,6 +620,27 @@ if (goog.DEBUG && !COMPILED) { */ proto.pactus.ConsensusInfo.displayName = 'proto.pactus.ConsensusInfo'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.pactus.Proposal = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.pactus.Proposal, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.pactus.Proposal.displayName = 'proto.pactus.Proposal'; +} @@ -3562,7 +3584,8 @@ proto.pactus.GetConsensusInfoResponse.prototype.toObject = function(opt_includeI proto.pactus.GetConsensusInfoResponse.toObject = function(includeInstance, msg) { var f, obj = { instancesList: jspb.Message.toObjectList(msg.getInstancesList(), - proto.pactus.ConsensusInfo.toObject, includeInstance) + proto.pactus.ConsensusInfo.toObject, includeInstance), + proposal: (f = msg.getProposal()) && proto.pactus.Proposal.toObject(includeInstance, f) }; if (includeInstance) { @@ -3604,6 +3627,11 @@ proto.pactus.GetConsensusInfoResponse.deserializeBinaryFromReader = function(msg reader.readMessage(value,proto.pactus.ConsensusInfo.deserializeBinaryFromReader); msg.addInstances(value); break; + case 6: + var value = new proto.pactus.Proposal; + reader.readMessage(value,proto.pactus.Proposal.deserializeBinaryFromReader); + msg.setProposal(value); + break; default: reader.skipField(); break; @@ -3641,6 +3669,14 @@ proto.pactus.GetConsensusInfoResponse.serializeBinaryToWriter = function(message proto.pactus.ConsensusInfo.serializeBinaryToWriter ); } + f = message.getProposal(); + if (f != null) { + writer.writeMessage( + 6, + f, + proto.pactus.Proposal.serializeBinaryToWriter + ); + } }; @@ -3682,6 +3718,43 @@ proto.pactus.GetConsensusInfoResponse.prototype.clearInstancesList = function() }; +/** + * optional Proposal proposal = 6; + * @return {?proto.pactus.Proposal} + */ +proto.pactus.GetConsensusInfoResponse.prototype.getProposal = function() { + return /** @type{?proto.pactus.Proposal} */ ( + jspb.Message.getWrapperField(this, proto.pactus.Proposal, 6)); +}; + + +/** + * @param {?proto.pactus.Proposal|undefined} value + * @return {!proto.pactus.GetConsensusInfoResponse} returns this +*/ +proto.pactus.GetConsensusInfoResponse.prototype.setProposal = function(value) { + return jspb.Message.setWrapperField(this, 6, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.pactus.GetConsensusInfoResponse} returns this + */ +proto.pactus.GetConsensusInfoResponse.prototype.clearProposal = function() { + return this.setProposal(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.pactus.GetConsensusInfoResponse.prototype.hasProposal = function() { + return jspb.Message.getField(this, 6) != null; +}; + + @@ -5731,6 +5804,226 @@ proto.pactus.ConsensusInfo.prototype.clearVotesList = function() { }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.pactus.Proposal.prototype.toObject = function(opt_includeInstance) { + return proto.pactus.Proposal.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.pactus.Proposal} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.pactus.Proposal.toObject = function(includeInstance, msg) { + var f, obj = { + height: jspb.Message.getFieldWithDefault(msg, 1, 0), + round: jspb.Message.getFieldWithDefault(msg, 2, 0), + blockData: jspb.Message.getFieldWithDefault(msg, 3, ""), + signatureData: jspb.Message.getFieldWithDefault(msg, 4, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.pactus.Proposal} + */ +proto.pactus.Proposal.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.pactus.Proposal; + return proto.pactus.Proposal.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.pactus.Proposal} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.pactus.Proposal} + */ +proto.pactus.Proposal.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {number} */ (reader.readUint32()); + msg.setHeight(value); + break; + case 2: + var value = /** @type {number} */ (reader.readInt32()); + msg.setRound(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setBlockData(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setSignatureData(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.pactus.Proposal.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.pactus.Proposal.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.pactus.Proposal} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.pactus.Proposal.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getHeight(); + if (f !== 0) { + writer.writeUint32( + 1, + f + ); + } + f = message.getRound(); + if (f !== 0) { + writer.writeInt32( + 2, + f + ); + } + f = message.getBlockData(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getSignatureData(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } +}; + + +/** + * optional uint32 height = 1; + * @return {number} + */ +proto.pactus.Proposal.prototype.getHeight = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.pactus.Proposal} returns this + */ +proto.pactus.Proposal.prototype.setHeight = function(value) { + return jspb.Message.setProto3IntField(this, 1, value); +}; + + +/** + * optional int32 round = 2; + * @return {number} + */ +proto.pactus.Proposal.prototype.getRound = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.pactus.Proposal} returns this + */ +proto.pactus.Proposal.prototype.setRound = function(value) { + return jspb.Message.setProto3IntField(this, 2, value); +}; + + +/** + * optional string block_data = 3; + * @return {string} + */ +proto.pactus.Proposal.prototype.getBlockData = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.pactus.Proposal} returns this + */ +proto.pactus.Proposal.prototype.setBlockData = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional string signature_data = 4; + * @return {string} + */ +proto.pactus.Proposal.prototype.getSignatureData = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.pactus.Proposal} returns this + */ +proto.pactus.Proposal.prototype.setSignatureData = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); +}; + + /** * @enum {number} */ diff --git a/www/grpc/gen/python/blockchain_pb2.py b/www/grpc/gen/python/blockchain_pb2.py index 4fd752f31..f79c1ad09 100644 --- a/www/grpc/gen/python/blockchain_pb2.py +++ b/www/grpc/gen/python/blockchain_pb2.py @@ -14,7 +14,7 @@ import transaction_pb2 as transaction__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x62lockchain.proto\x12\x06pactus\x1a\x11transaction.proto\"-\n\x11GetAccountRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"C\n\x12GetAccountResponse\x12-\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x13.pactus.AccountInfoR\x07\x61\x63\x63ount\"\x1e\n\x1cGetValidatorAddressesRequest\"=\n\x1dGetValidatorAddressesResponse\x12\x1c\n\taddresses\x18\x01 \x03(\tR\taddresses\"/\n\x13GetValidatorRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x1bGetValidatorByNumberRequest\x12\x16\n\x06number\x18\x01 \x01(\x05R\x06number\"K\n\x14GetValidatorResponse\x12\x33\n\tvalidator\x18\x01 \x01(\x0b\x32\x15.pactus.ValidatorInfoR\tvalidator\"/\n\x13GetPublicKeyRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x14GetPublicKeyResponse\x12\x1d\n\npublic_key\x18\x01 \x01(\tR\tpublicKey\"_\n\x0fGetBlockRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x34\n\tverbosity\x18\x02 \x01(\x0e\x32\x16.pactus.BlockVerbosityR\tverbosity\"\x83\x02\n\x10GetBlockResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x12\n\x04hash\x18\x02 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x03 \x01(\tR\x04\x64\x61ta\x12\x1d\n\nblock_time\x18\x04 \x01(\rR\tblockTime\x12/\n\x06header\x18\x05 \x01(\x0b\x32\x17.pactus.BlockHeaderInfoR\x06header\x12\x34\n\tprev_cert\x18\x06 \x01(\x0b\x32\x17.pactus.CertificateInfoR\x08prevCert\x12)\n\x03txs\x18\x07 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"-\n\x13GetBlockHashRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"*\n\x14GetBlockHashResponse\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"+\n\x15GetBlockHeightRequest\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"0\n\x16GetBlockHeightResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"\x1a\n\x18GetBlockchainInfoRequest\"\xc1\x03\n\x19GetBlockchainInfoResponse\x12*\n\x11last_block_height\x18\x01 \x01(\rR\x0flastBlockHeight\x12&\n\x0flast_block_hash\x18\x02 \x01(\tR\rlastBlockHash\x12%\n\x0etotal_accounts\x18\x03 \x01(\x05R\rtotalAccounts\x12)\n\x10total_validators\x18\x04 \x01(\x05R\x0ftotalValidators\x12\x1f\n\x0btotal_power\x18\x05 \x01(\x03R\ntotalPower\x12\'\n\x0f\x63ommittee_power\x18\x06 \x01(\x03R\x0e\x63ommitteePower\x12H\n\x14\x63ommittee_validators\x18\x07 \x03(\x0b\x32\x15.pactus.ValidatorInfoR\x13\x63ommitteeValidators\x12\x1b\n\tis_pruned\x18\x08 \x01(\x08R\x08isPruned\x12%\n\x0epruning_height\x18\t \x01(\rR\rpruningHeight\x12&\n\x0flast_block_time\x18\n \x01(\x03R\rlastBlockTime\"\x19\n\x17GetConsensusInfoRequest\"O\n\x18GetConsensusInfoResponse\x12\x33\n\tinstances\x18\x01 \x03(\x0b\x32\x15.pactus.ConsensusInfoR\tinstances\"Q\n\x17GetTxPoolContentRequest\x12\x36\n\x0cpayload_type\x18\x01 \x01(\x0e\x32\x13.pactus.PayloadTypeR\x0bpayloadType\"E\n\x18GetTxPoolContentResponse\x12)\n\x03txs\x18\x01 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"\xdc\x02\n\rValidatorInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x1d\n\npublic_key\x18\x03 \x01(\tR\tpublicKey\x12\x16\n\x06number\x18\x04 \x01(\x05R\x06number\x12\x14\n\x05stake\x18\x05 \x01(\x03R\x05stake\x12.\n\x13last_bonding_height\x18\x06 \x01(\rR\x11lastBondingHeight\x12\x32\n\x15last_sortition_height\x18\x07 \x01(\rR\x13lastSortitionHeight\x12)\n\x10unbonding_height\x18\x08 \x01(\rR\x0funbondingHeight\x12\x18\n\x07\x61\x64\x64ress\x18\t \x01(\tR\x07\x61\x64\x64ress\x12-\n\x12\x61vailability_score\x18\n \x01(\x01R\x11\x61vailabilityScore\"\x81\x01\n\x0b\x41\x63\x63ountInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x16\n\x06number\x18\x03 \x01(\x05R\x06number\x12\x18\n\x07\x62\x61lance\x18\x04 \x01(\x03R\x07\x62\x61lance\x12\x18\n\x07\x61\x64\x64ress\x18\x05 \x01(\tR\x07\x61\x64\x64ress\"\xc4\x01\n\x0f\x42lockHeaderInfo\x12\x18\n\x07version\x18\x01 \x01(\x05R\x07version\x12&\n\x0fprev_block_hash\x18\x02 \x01(\tR\rprevBlockHash\x12\x1d\n\nstate_root\x18\x03 \x01(\tR\tstateRoot\x12%\n\x0esortition_seed\x18\x04 \x01(\tR\rsortitionSeed\x12)\n\x10proposer_address\x18\x05 \x01(\tR\x0fproposerAddress\"\x97\x01\n\x0f\x43\x65rtificateInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1e\n\ncommitters\x18\x03 \x03(\x05R\ncommitters\x12\x1c\n\tabsentees\x18\x04 \x03(\x05R\tabsentees\x12\x1c\n\tsignature\x18\x05 \x01(\tR\tsignature\"\xb1\x01\n\x08VoteInfo\x12$\n\x04type\x18\x01 \x01(\x0e\x32\x10.pactus.VoteTypeR\x04type\x12\x14\n\x05voter\x18\x02 \x01(\tR\x05voter\x12\x1d\n\nblock_hash\x18\x03 \x01(\tR\tblockHash\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12\x19\n\x08\x63p_round\x18\x05 \x01(\x05R\x07\x63pRound\x12\x19\n\x08\x63p_value\x18\x06 \x01(\x05R\x07\x63pValue\"\x97\x01\n\rConsensusInfo\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\x12\x16\n\x06\x61\x63tive\x18\x02 \x01(\x08R\x06\x61\x63tive\x12\x16\n\x06height\x18\x03 \x01(\rR\x06height\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12&\n\x05votes\x18\x05 \x03(\x0b\x32\x10.pactus.VoteInfoR\x05votes*H\n\x0e\x42lockVerbosity\x12\x0e\n\nBLOCK_DATA\x10\x00\x12\x0e\n\nBLOCK_INFO\x10\x01\x12\x16\n\x12\x42LOCK_TRANSACTIONS\x10\x02*\\\n\x08VoteType\x12\x10\n\x0cVOTE_UNKNOWN\x10\x00\x12\x10\n\x0cVOTE_PREPARE\x10\x01\x12\x12\n\x0eVOTE_PRECOMMIT\x10\x02\x12\x18\n\x14VOTE_CHANGE_PROPOSER\x10\x03\x32\x8b\x07\n\nBlockchain\x12=\n\x08GetBlock\x12\x17.pactus.GetBlockRequest\x1a\x18.pactus.GetBlockResponse\x12I\n\x0cGetBlockHash\x12\x1b.pactus.GetBlockHashRequest\x1a\x1c.pactus.GetBlockHashResponse\x12O\n\x0eGetBlockHeight\x12\x1d.pactus.GetBlockHeightRequest\x1a\x1e.pactus.GetBlockHeightResponse\x12X\n\x11GetBlockchainInfo\x12 .pactus.GetBlockchainInfoRequest\x1a!.pactus.GetBlockchainInfoResponse\x12U\n\x10GetConsensusInfo\x12\x1f.pactus.GetConsensusInfoRequest\x1a .pactus.GetConsensusInfoResponse\x12\x43\n\nGetAccount\x12\x19.pactus.GetAccountRequest\x1a\x1a.pactus.GetAccountResponse\x12I\n\x0cGetValidator\x12\x1b.pactus.GetValidatorRequest\x1a\x1c.pactus.GetValidatorResponse\x12Y\n\x14GetValidatorByNumber\x12#.pactus.GetValidatorByNumberRequest\x1a\x1c.pactus.GetValidatorResponse\x12\x64\n\x15GetValidatorAddresses\x12$.pactus.GetValidatorAddressesRequest\x1a%.pactus.GetValidatorAddressesResponse\x12I\n\x0cGetPublicKey\x12\x1b.pactus.GetPublicKeyRequest\x1a\x1c.pactus.GetPublicKeyResponse\x12U\n\x10GetTxPoolContent\x12\x1f.pactus.GetTxPoolContentRequest\x1a .pactus.GetTxPoolContentResponseBE\n\x11pactus.blockchainZ0github.com/pactus-project/pactus/www/grpc/pactusb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x62lockchain.proto\x12\x06pactus\x1a\x11transaction.proto\"-\n\x11GetAccountRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"C\n\x12GetAccountResponse\x12-\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x13.pactus.AccountInfoR\x07\x61\x63\x63ount\"\x1e\n\x1cGetValidatorAddressesRequest\"=\n\x1dGetValidatorAddressesResponse\x12\x1c\n\taddresses\x18\x01 \x03(\tR\taddresses\"/\n\x13GetValidatorRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x1bGetValidatorByNumberRequest\x12\x16\n\x06number\x18\x01 \x01(\x05R\x06number\"K\n\x14GetValidatorResponse\x12\x33\n\tvalidator\x18\x01 \x01(\x0b\x32\x15.pactus.ValidatorInfoR\tvalidator\"/\n\x13GetPublicKeyRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x14GetPublicKeyResponse\x12\x1d\n\npublic_key\x18\x01 \x01(\tR\tpublicKey\"_\n\x0fGetBlockRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x34\n\tverbosity\x18\x02 \x01(\x0e\x32\x16.pactus.BlockVerbosityR\tverbosity\"\x83\x02\n\x10GetBlockResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x12\n\x04hash\x18\x02 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x03 \x01(\tR\x04\x64\x61ta\x12\x1d\n\nblock_time\x18\x04 \x01(\rR\tblockTime\x12/\n\x06header\x18\x05 \x01(\x0b\x32\x17.pactus.BlockHeaderInfoR\x06header\x12\x34\n\tprev_cert\x18\x06 \x01(\x0b\x32\x17.pactus.CertificateInfoR\x08prevCert\x12)\n\x03txs\x18\x07 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"-\n\x13GetBlockHashRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"*\n\x14GetBlockHashResponse\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"+\n\x15GetBlockHeightRequest\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"0\n\x16GetBlockHeightResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"\x1a\n\x18GetBlockchainInfoRequest\"\xc1\x03\n\x19GetBlockchainInfoResponse\x12*\n\x11last_block_height\x18\x01 \x01(\rR\x0flastBlockHeight\x12&\n\x0flast_block_hash\x18\x02 \x01(\tR\rlastBlockHash\x12%\n\x0etotal_accounts\x18\x03 \x01(\x05R\rtotalAccounts\x12)\n\x10total_validators\x18\x04 \x01(\x05R\x0ftotalValidators\x12\x1f\n\x0btotal_power\x18\x05 \x01(\x03R\ntotalPower\x12\'\n\x0f\x63ommittee_power\x18\x06 \x01(\x03R\x0e\x63ommitteePower\x12H\n\x14\x63ommittee_validators\x18\x07 \x03(\x0b\x32\x15.pactus.ValidatorInfoR\x13\x63ommitteeValidators\x12\x1b\n\tis_pruned\x18\x08 \x01(\x08R\x08isPruned\x12%\n\x0epruning_height\x18\t \x01(\rR\rpruningHeight\x12&\n\x0flast_block_time\x18\n \x01(\x03R\rlastBlockTime\"\x19\n\x17GetConsensusInfoRequest\"}\n\x18GetConsensusInfoResponse\x12\x33\n\tinstances\x18\x01 \x03(\x0b\x32\x15.pactus.ConsensusInfoR\tinstances\x12,\n\x08proposal\x18\x06 \x01(\x0b\x32\x10.pactus.ProposalR\x08proposal\"Q\n\x17GetTxPoolContentRequest\x12\x36\n\x0cpayload_type\x18\x01 \x01(\x0e\x32\x13.pactus.PayloadTypeR\x0bpayloadType\"E\n\x18GetTxPoolContentResponse\x12)\n\x03txs\x18\x01 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"\xdc\x02\n\rValidatorInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x1d\n\npublic_key\x18\x03 \x01(\tR\tpublicKey\x12\x16\n\x06number\x18\x04 \x01(\x05R\x06number\x12\x14\n\x05stake\x18\x05 \x01(\x03R\x05stake\x12.\n\x13last_bonding_height\x18\x06 \x01(\rR\x11lastBondingHeight\x12\x32\n\x15last_sortition_height\x18\x07 \x01(\rR\x13lastSortitionHeight\x12)\n\x10unbonding_height\x18\x08 \x01(\rR\x0funbondingHeight\x12\x18\n\x07\x61\x64\x64ress\x18\t \x01(\tR\x07\x61\x64\x64ress\x12-\n\x12\x61vailability_score\x18\n \x01(\x01R\x11\x61vailabilityScore\"\x81\x01\n\x0b\x41\x63\x63ountInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x16\n\x06number\x18\x03 \x01(\x05R\x06number\x12\x18\n\x07\x62\x61lance\x18\x04 \x01(\x03R\x07\x62\x61lance\x12\x18\n\x07\x61\x64\x64ress\x18\x05 \x01(\tR\x07\x61\x64\x64ress\"\xc4\x01\n\x0f\x42lockHeaderInfo\x12\x18\n\x07version\x18\x01 \x01(\x05R\x07version\x12&\n\x0fprev_block_hash\x18\x02 \x01(\tR\rprevBlockHash\x12\x1d\n\nstate_root\x18\x03 \x01(\tR\tstateRoot\x12%\n\x0esortition_seed\x18\x04 \x01(\tR\rsortitionSeed\x12)\n\x10proposer_address\x18\x05 \x01(\tR\x0fproposerAddress\"\x97\x01\n\x0f\x43\x65rtificateInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1e\n\ncommitters\x18\x03 \x03(\x05R\ncommitters\x12\x1c\n\tabsentees\x18\x04 \x03(\x05R\tabsentees\x12\x1c\n\tsignature\x18\x05 \x01(\tR\tsignature\"\xb1\x01\n\x08VoteInfo\x12$\n\x04type\x18\x01 \x01(\x0e\x32\x10.pactus.VoteTypeR\x04type\x12\x14\n\x05voter\x18\x02 \x01(\tR\x05voter\x12\x1d\n\nblock_hash\x18\x03 \x01(\tR\tblockHash\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12\x19\n\x08\x63p_round\x18\x05 \x01(\x05R\x07\x63pRound\x12\x19\n\x08\x63p_value\x18\x06 \x01(\x05R\x07\x63pValue\"\x97\x01\n\rConsensusInfo\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\x12\x16\n\x06\x61\x63tive\x18\x02 \x01(\x08R\x06\x61\x63tive\x12\x16\n\x06height\x18\x03 \x01(\rR\x06height\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12&\n\x05votes\x18\x05 \x03(\x0b\x32\x10.pactus.VoteInfoR\x05votes\"~\n\x08Proposal\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1d\n\nblock_data\x18\x03 \x01(\tR\tblockData\x12%\n\x0esignature_data\x18\x04 \x01(\tR\rsignatureData*H\n\x0e\x42lockVerbosity\x12\x0e\n\nBLOCK_DATA\x10\x00\x12\x0e\n\nBLOCK_INFO\x10\x01\x12\x16\n\x12\x42LOCK_TRANSACTIONS\x10\x02*\\\n\x08VoteType\x12\x10\n\x0cVOTE_UNKNOWN\x10\x00\x12\x10\n\x0cVOTE_PREPARE\x10\x01\x12\x12\n\x0eVOTE_PRECOMMIT\x10\x02\x12\x18\n\x14VOTE_CHANGE_PROPOSER\x10\x03\x32\x8b\x07\n\nBlockchain\x12=\n\x08GetBlock\x12\x17.pactus.GetBlockRequest\x1a\x18.pactus.GetBlockResponse\x12I\n\x0cGetBlockHash\x12\x1b.pactus.GetBlockHashRequest\x1a\x1c.pactus.GetBlockHashResponse\x12O\n\x0eGetBlockHeight\x12\x1d.pactus.GetBlockHeightRequest\x1a\x1e.pactus.GetBlockHeightResponse\x12X\n\x11GetBlockchainInfo\x12 .pactus.GetBlockchainInfoRequest\x1a!.pactus.GetBlockchainInfoResponse\x12U\n\x10GetConsensusInfo\x12\x1f.pactus.GetConsensusInfoRequest\x1a .pactus.GetConsensusInfoResponse\x12\x43\n\nGetAccount\x12\x19.pactus.GetAccountRequest\x1a\x1a.pactus.GetAccountResponse\x12I\n\x0cGetValidator\x12\x1b.pactus.GetValidatorRequest\x1a\x1c.pactus.GetValidatorResponse\x12Y\n\x14GetValidatorByNumber\x12#.pactus.GetValidatorByNumberRequest\x1a\x1c.pactus.GetValidatorResponse\x12\x64\n\x15GetValidatorAddresses\x12$.pactus.GetValidatorAddressesRequest\x1a%.pactus.GetValidatorAddressesResponse\x12I\n\x0cGetPublicKey\x12\x1b.pactus.GetPublicKeyRequest\x1a\x1c.pactus.GetPublicKeyResponse\x12U\n\x10GetTxPoolContent\x12\x1f.pactus.GetTxPoolContentRequest\x1a .pactus.GetTxPoolContentResponseBE\n\x11pactus.blockchainZ0github.com/pactus-project/pactus/www/grpc/pactusb\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'blockchain_pb2', globals()) @@ -22,10 +22,10 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n\021pactus.blockchainZ0github.com/pactus-project/pactus/www/grpc/pactus' - _BLOCKVERBOSITY._serialized_start=3000 - _BLOCKVERBOSITY._serialized_end=3072 - _VOTETYPE._serialized_start=3074 - _VOTETYPE._serialized_end=3166 + _BLOCKVERBOSITY._serialized_start=3174 + _BLOCKVERBOSITY._serialized_end=3246 + _VOTETYPE._serialized_start=3248 + _VOTETYPE._serialized_end=3340 _GETACCOUNTREQUEST._serialized_start=47 _GETACCOUNTREQUEST._serialized_end=92 _GETACCOUNTRESPONSE._serialized_start=94 @@ -63,23 +63,25 @@ _GETCONSENSUSINFOREQUEST._serialized_start=1568 _GETCONSENSUSINFOREQUEST._serialized_end=1593 _GETCONSENSUSINFORESPONSE._serialized_start=1595 - _GETCONSENSUSINFORESPONSE._serialized_end=1674 - _GETTXPOOLCONTENTREQUEST._serialized_start=1676 - _GETTXPOOLCONTENTREQUEST._serialized_end=1757 - _GETTXPOOLCONTENTRESPONSE._serialized_start=1759 - _GETTXPOOLCONTENTRESPONSE._serialized_end=1828 - _VALIDATORINFO._serialized_start=1831 - _VALIDATORINFO._serialized_end=2179 - _ACCOUNTINFO._serialized_start=2182 - _ACCOUNTINFO._serialized_end=2311 - _BLOCKHEADERINFO._serialized_start=2314 - _BLOCKHEADERINFO._serialized_end=2510 - _CERTIFICATEINFO._serialized_start=2513 - _CERTIFICATEINFO._serialized_end=2664 - _VOTEINFO._serialized_start=2667 - _VOTEINFO._serialized_end=2844 - _CONSENSUSINFO._serialized_start=2847 - _CONSENSUSINFO._serialized_end=2998 - _BLOCKCHAIN._serialized_start=3169 - _BLOCKCHAIN._serialized_end=4076 + _GETCONSENSUSINFORESPONSE._serialized_end=1720 + _GETTXPOOLCONTENTREQUEST._serialized_start=1722 + _GETTXPOOLCONTENTREQUEST._serialized_end=1803 + _GETTXPOOLCONTENTRESPONSE._serialized_start=1805 + _GETTXPOOLCONTENTRESPONSE._serialized_end=1874 + _VALIDATORINFO._serialized_start=1877 + _VALIDATORINFO._serialized_end=2225 + _ACCOUNTINFO._serialized_start=2228 + _ACCOUNTINFO._serialized_end=2357 + _BLOCKHEADERINFO._serialized_start=2360 + _BLOCKHEADERINFO._serialized_end=2556 + _CERTIFICATEINFO._serialized_start=2559 + _CERTIFICATEINFO._serialized_end=2710 + _VOTEINFO._serialized_start=2713 + _VOTEINFO._serialized_end=2890 + _CONSENSUSINFO._serialized_start=2893 + _CONSENSUSINFO._serialized_end=3044 + _PROPOSAL._serialized_start=3046 + _PROPOSAL._serialized_end=3172 + _BLOCKCHAIN._serialized_start=3343 + _BLOCKCHAIN._serialized_end=4250 # @@protoc_insertion_point(module_scope) diff --git a/www/grpc/gen/rust/pactus.rs b/www/grpc/gen/rust/pactus.rs index 0ee61993b..d9b89a303 100644 --- a/www/grpc/gen/rust/pactus.rs +++ b/www/grpc/gen/rust/pactus.rs @@ -548,6 +548,9 @@ pub struct GetConsensusInfoResponse { /// List of consensus instances. #[prost(message, repeated, tag="1")] pub instances: ::prost::alloc::vec::Vec, + /// The proposal of the consensus info. + #[prost(message, optional, tag="6")] + pub proposal: ::core::option::Option, } /// Request message to retrieve transactions in the transaction pool. #[allow(clippy::derive_partial_eq_without_eq)] @@ -705,6 +708,23 @@ pub struct ConsensusInfo { #[prost(message, repeated, tag="5")] pub votes: ::prost::alloc::vec::Vec, } +/// Message containing information about a proposal. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Proposal { + /// The height of the proposal. + #[prost(uint32, tag="1")] + pub height: u32, + /// The round of the proposal. + #[prost(int32, tag="2")] + pub round: i32, + /// The block data of the proposal. + #[prost(string, tag="3")] + pub block_data: ::prost::alloc::string::String, + /// The signature data of the proposal. + #[prost(string, tag="4")] + pub signature_data: ::prost::alloc::string::String, +} /// Enumeration for verbosity levels when requesting block information. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] diff --git a/www/grpc/gen/rust/pactus.serde.rs b/www/grpc/gen/rust/pactus.serde.rs index 8b34387f3..c62bf4ab1 100644 --- a/www/grpc/gen/rust/pactus.serde.rs +++ b/www/grpc/gen/rust/pactus.serde.rs @@ -3194,10 +3194,16 @@ impl serde::Serialize for GetConsensusInfoResponse { if !self.instances.is_empty() { len += 1; } + if self.proposal.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("pactus.GetConsensusInfoResponse", len)?; if !self.instances.is_empty() { struct_ser.serialize_field("instances", &self.instances)?; } + if let Some(v) = self.proposal.as_ref() { + struct_ser.serialize_field("proposal", v)?; + } struct_ser.end() } } @@ -3209,11 +3215,13 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { { const FIELDS: &[&str] = &[ "instances", + "proposal", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Instances, + Proposal, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -3236,6 +3244,7 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { { match value { "instances" => Ok(GeneratedField::Instances), + "proposal" => Ok(GeneratedField::Proposal), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -3256,6 +3265,7 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { V: serde::de::MapAccess<'de>, { let mut instances__ = None; + let mut proposal__ = None; while let Some(k) = map.next_key()? { match k { GeneratedField::Instances => { @@ -3264,10 +3274,17 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { } instances__ = Some(map.next_value()?); } + GeneratedField::Proposal => { + if proposal__.is_some() { + return Err(serde::de::Error::duplicate_field("proposal")); + } + proposal__ = map.next_value()?; + } } } Ok(GetConsensusInfoResponse { instances: instances__.unwrap_or_default(), + proposal: proposal__, }) } } @@ -7856,6 +7873,154 @@ impl<'de> serde::Deserialize<'de> for PeerInfo { deserializer.deserialize_struct("pactus.PeerInfo", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for Proposal { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.height != 0 { + len += 1; + } + if self.round != 0 { + len += 1; + } + if !self.block_data.is_empty() { + len += 1; + } + if !self.signature_data.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("pactus.Proposal", len)?; + if self.height != 0 { + struct_ser.serialize_field("height", &self.height)?; + } + if self.round != 0 { + struct_ser.serialize_field("round", &self.round)?; + } + if !self.block_data.is_empty() { + struct_ser.serialize_field("blockData", &self.block_data)?; + } + if !self.signature_data.is_empty() { + struct_ser.serialize_field("signatureData", &self.signature_data)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Proposal { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "height", + "round", + "block_data", + "blockData", + "signature_data", + "signatureData", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Height, + Round, + BlockData, + SignatureData, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "height" => Ok(GeneratedField::Height), + "round" => Ok(GeneratedField::Round), + "blockData" | "block_data" => Ok(GeneratedField::BlockData), + "signatureData" | "signature_data" => Ok(GeneratedField::SignatureData), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Proposal; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct pactus.Proposal") + } + + fn visit_map(self, mut map: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut height__ = None; + let mut round__ = None; + let mut block_data__ = None; + let mut signature_data__ = None; + while let Some(k) = map.next_key()? { + match k { + GeneratedField::Height => { + if height__.is_some() { + return Err(serde::de::Error::duplicate_field("height")); + } + height__ = + Some(map.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Round => { + if round__.is_some() { + return Err(serde::de::Error::duplicate_field("round")); + } + round__ = + Some(map.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::BlockData => { + if block_data__.is_some() { + return Err(serde::de::Error::duplicate_field("blockData")); + } + block_data__ = Some(map.next_value()?); + } + GeneratedField::SignatureData => { + if signature_data__.is_some() { + return Err(serde::de::Error::duplicate_field("signatureData")); + } + signature_data__ = Some(map.next_value()?); + } + } + } + Ok(Proposal { + height: height__.unwrap_or_default(), + round: round__.unwrap_or_default(), + block_data: block_data__.unwrap_or_default(), + signature_data: signature_data__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("pactus.Proposal", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for RestoreWalletRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/www/grpc/proto/blockchain.proto b/www/grpc/proto/blockchain.proto index 95e58efc4..7dc4f2082 100644 --- a/www/grpc/proto/blockchain.proto +++ b/www/grpc/proto/blockchain.proto @@ -186,8 +186,10 @@ message GetConsensusInfoRequest {} // Message containing the response with consensus information. message GetConsensusInfoResponse { + // The proposal of the consensus info. + Proposal proposal = 1; // List of consensus instances. - repeated ConsensusInfo instances = 1; + repeated ConsensusInfo instances = 2; } // Request message to retrieve transactions in the transaction pool. @@ -300,6 +302,20 @@ message ConsensusInfo { repeated VoteInfo votes = 5; } +// Message containing information about a proposal. +message Proposal { + // The height of the proposal. + uint32 height = 1; + // The round of the proposal. + int32 round = 2; + // The block data of the proposal. + string block_data = 3; + // The signature data of the proposal. + string signature_data = 4; +} + + + // Enumeration for verbosity levels when requesting block information. enum BlockVerbosity { // Request only block data. diff --git a/www/grpc/swagger-ui/pactus.swagger.json b/www/grpc/swagger-ui/pactus.swagger.json index fb438593b..293fcad78 100644 --- a/www/grpc/swagger-ui/pactus.swagger.json +++ b/www/grpc/swagger-ui/pactus.swagger.json @@ -1643,6 +1643,10 @@ "$ref": "#/definitions/pactusConsensusInfo" }, "description": "List of consensus instances." + }, + "proposal": { + "$ref": "#/definitions/pactusProposal", + "description": "The proposal of the consensus info." } }, "description": "Message containing the response with consensus information." @@ -2115,6 +2119,30 @@ }, "description": "Information about a peer in the network." }, + "pactusProposal": { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int64", + "description": "The height of the proposal." + }, + "round": { + "type": "integer", + "format": "int32", + "description": "The round of the proposal." + }, + "blockData": { + "type": "string", + "description": "The block data of the proposal." + }, + "signatureData": { + "type": "string", + "description": "The signature data of the proposal." + } + }, + "description": "Message containing information about a proposal." + }, "pactusRestoreWalletResponse": { "type": "object", "properties": { diff --git a/www/http/blockchain.go b/www/http/blockchain.go index f925e9e5d..d2e4bbf71 100644 --- a/www/http/blockchain.go +++ b/www/http/blockchain.go @@ -233,6 +233,14 @@ func (s *Server) ConsensusHandler(w http.ResponseWriter, r *http.Request) { } tm := newTableMaker() + + if res.Proposal != nil { + tm.addRowInt("Proposal == Height", int(res.Proposal.Height)) + tm.addRowInt("Proposal == Round", int(res.Proposal.Round)) + tm.addRowString("Proposal == BlockData", res.Proposal.BlockData) + tm.addRowString("Proposal == SignatureData", res.Proposal.SignatureData) + } + for i, cons := range res.Instances { tm.addRowInt("== Validator", i+1) tm.addRowValAddress("Address", cons.Address) @@ -250,5 +258,6 @@ func (s *Server) ConsensusHandler(w http.ResponseWriter, r *http.Request) { tm.addRowBlockHash("BlockHash", v.BlockHash) } } + s.writeHTML(w, tm.html()) } From d30aa0368ce4f3b266f81f9b6478b52336e01d78 Mon Sep 17 00:00:00 2001 From: Muhammad Javad Akbarian <94112796+akbariandev@users.noreply.github.com> Date: Sat, 24 Aug 2024 13:29:10 +0330 Subject: [PATCH 18/25] feat(wallet): supporting Ed25519 curve in wallet (#1484) Co-authored-by: mj --- cmd/wallet/address.go | 3 + crypto/address.go | 3 +- crypto/address_test.go | 98 ++++++++++++++------- types/tx/errors.go | 9 +- types/tx/tx.go | 101 ++++++++++++++++++---- types/tx/tx_test.go | 99 +++++++++++++++++++--- util/testsuite/testsuite.go | 11 ++- wallet/vault/vault.go | 164 ++++++++++++++++++++++++++++-------- wallet/vault/vault_test.go | 22 +++++ wallet/wallet.go | 19 ++++- wallet/wallet_test.go | 31 ++++++- 11 files changed, 461 insertions(+), 99 deletions(-) diff --git a/cmd/wallet/address.go b/cmd/wallet/address.go index 170813350..1134e520a 100644 --- a/cmd/wallet/address.go +++ b/cmd/wallet/address.go @@ -86,6 +86,9 @@ func buildNewAddressCmd(parentCmd *cobra.Command) { if *addressType == wallet.AddressTypeBLSAccount { addressInfo, err = wlt.NewBLSAccountAddress(label) + } else if *addressType == wallet.AddressTypeEd25519Account { + password := cmd.PromptInput("Password") + addressInfo, err = wlt.NewEd25519AccountAddress(label, password) } else if *addressType == wallet.AddressTypeValidator { addressInfo, err = wlt.NewValidatorAddress(label) } else { diff --git a/crypto/address.go b/crypto/address.go index 536a93505..fd26b6e46 100644 --- a/crypto/address.go +++ b/crypto/address.go @@ -164,7 +164,8 @@ func (addr Address) IsTreasuryAddress() bool { func (addr Address) IsAccountAddress() bool { return addr.Type() == AddressTypeTreasury || - addr.Type() == AddressTypeBLSAccount + addr.Type() == AddressTypeBLSAccount || + addr.Type() == AddressTypeEd25519Account } func (addr Address) IsValidatorAddress() bool { diff --git a/crypto/address_test.go b/crypto/address_test.go index 6bc28b3af..21733f8a0 100644 --- a/crypto/address_test.go +++ b/crypto/address_test.go @@ -3,7 +3,6 @@ package crypto_test import ( "bytes" "encoding/hex" - "fmt" "io" "strings" "testing" @@ -15,109 +14,145 @@ import ( "github.com/stretchr/testify/assert" ) -func TestAddressKeyType(t *testing.T) { - ts := testsuite.NewTestSuite(t) - - pub, _ := ts.RandBLSKeyPair() - accAddr := pub.AccountAddress() - valAddr := pub.ValidatorAddress() +func TestTreasuryAddressType(t *testing.T) { treasury := crypto.TreasuryAddress - assert.True(t, accAddr.IsAccountAddress()) - assert.False(t, accAddr.IsValidatorAddress()) - assert.False(t, accAddr.IsTreasuryAddress()) - assert.False(t, valAddr.IsAccountAddress()) - assert.True(t, valAddr.IsValidatorAddress()) assert.False(t, treasury.IsValidatorAddress()) assert.True(t, treasury.IsAccountAddress()) assert.True(t, treasury.IsTreasuryAddress()) - assert.NotEqual(t, accAddr, valAddr) } -func TestString(t *testing.T) { - ts := testsuite.NewTestSuite(t) +func TestAddressType(t *testing.T) { + tests := []struct { + address string + account bool + validator bool + }{ + {address: "pc1p0hrct7eflrpw4ccrttxzs4qud2axex4dcdzdfr", account: false, validator: true}, + {address: "pc1zzqkzzu4vyddss052as6c37qrdcfptegquw826x", account: true, validator: false}, + {address: "pc1rspm7ps49gar9ft5g0tkl6lhxs8ygeakq87quh3", account: true, validator: false}, + } + + for _, test := range tests { + addr, _ := crypto.AddressFromString(test.address) + + assert.Equal(t, test.account, addr.IsAccountAddress()) + assert.Equal(t, test.validator, addr.IsValidatorAddress()) + } +} - a, _ := crypto.AddressFromString("pc1p0hrct7eflrpw4ccrttxzs4qud2axex4dcdzdfr") - fmt.Println(a.String()) +func TestShortString(t *testing.T) { + ts := testsuite.NewTestSuite(t) addr1 := ts.RandAccAddress() assert.Contains(t, addr1.String(), addr1.ShortString()) } -func TestToString(t *testing.T) { +func TestFromString(t *testing.T) { tests := []struct { - encoded string - err error - result *crypto.Address + encoded string + err error + bytes []byte + addrType crypto.AddressType }{ { "000000000000000000000000000000000000000000", nil, - &crypto.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + crypto.AddressTypeTreasury, }, { "", bech32m.InvalidLengthError(0), nil, + 0, }, { "not_proper_encoded", bech32m.InvalidSeparatorIndexError(-1), nil, + 0, }, { "pc1ioiooi", bech32m.NonCharsetCharError(105), nil, + 0, }, { "pc19p72rf", bech32m.InvalidLengthError(0), nil, + 0, }, { "qc1z0hrct7eflrpw4ccrttxzs4qud2axex4dh8zz75", crypto.InvalidHRPError("qc"), nil, + 0, }, { "pc1p0hrct7eflrpw4ccrttxzs4qud2axex4dg8xaf5", bech32m.InvalidChecksumError{Expected: "cdzdfr", Actual: "g8xaf5"}, nil, + 0, }, { "pc1p0hrct7eflrpw4ccrttxzs4qud2axexs2dhdk8", crypto.InvalidLengthError(20), nil, + 0, }, { "pc1y0hrct7eflrpw4ccrttxzs4qud2axex4dksmred", crypto.InvalidAddressTypeError(4), nil, + 0, }, { "PC1P0HRCT7EFLRPW4CCRTTXZS4QUD2AXEX4DCDZDFR", // UPPERCASE nil, - &crypto.Address{ - 0x1, 0x7d, 0xc7, 0x85, 0xfb, 0x29, 0xf8, 0xc2, 0xea, 0xe3, - 0x3, 0x5a, 0xcc, 0x28, 0x54, 0x1c, 0x6a, 0xba, 0x6c, 0x9a, 0xad, + []byte{ + 0x01, 0x7d, 0xc7, 0x85, 0xfb, 0x29, 0xf8, 0xc2, 0xea, 0xe3, + 0x03, 0x5a, 0xcc, 0x28, 0x54, 0x1c, 0x6a, 0xba, 0x6c, 0x9a, 0xad, }, + crypto.AddressTypeValidator, }, { "pc1p0hrct7eflrpw4ccrttxzs4qud2axex4dcdzdfr", nil, - &crypto.Address{ - 0x1, 0x7d, 0xc7, 0x85, 0xfb, 0x29, 0xf8, 0xc2, 0xea, 0xe3, - 0x3, 0x5a, 0xcc, 0x28, 0x54, 0x1c, 0x6a, 0xba, 0x6c, 0x9a, 0xad, + []byte{ + 0x01, 0x7d, 0xc7, 0x85, 0xfb, 0x29, 0xf8, 0xc2, 0xea, 0xe3, + 0x03, 0x5a, 0xcc, 0x28, 0x54, 0x1c, 0x6a, 0xba, 0x6c, 0x9a, 0xad, + }, + crypto.AddressTypeValidator, + }, + { + "pc1zzqkzzu4vyddss052as6c37qrdcfptegquw826x", + nil, + []byte{ + 0x02, 0x10, 0x2c, 0x21, 0x72, 0xac, 0x23, 0x5b, 0x08, 0x3e, 0x8a, + 0xec, 0x35, 0x88, 0xf8, 0x03, 0x6e, 0x12, 0x15, 0xe5, 0x00, }, + crypto.AddressTypeBLSAccount, + }, + { + "pc1rspm7ps49gar9ft5g0tkl6lhxs8ygeakq87quh3", + nil, + []byte{ + 0x03, 0x80, 0x77, 0xe0, 0xc2, 0xa5, 0x47, 0x46, 0x54, 0xae, + 0x88, 0x7a, 0xed, 0xfd, 0x7e, 0xe6, 0x81, 0xc8, 0x8c, 0xf6, 0xc0, + }, + crypto.AddressTypeEd25519Account, }, } for no, test := range tests { addr, err := crypto.AddressFromString(test.encoded) if test.err == nil { assert.NoError(t, err, "test %v: unexpected error", no) - assert.Equal(t, *test.result, addr, "test %v: invalid result", no) + assert.Equal(t, test.bytes, addr.Bytes(), "test %v: invalid result", no) assert.Equal(t, strings.ToLower(test.encoded), addr.String(), "test %v: invalid encode", no) + assert.Equal(t, test.addrType, addr.Type(), "test %v: invalid type", no) } else { assert.ErrorIs(t, err, test.err, "test %v: invalid error", no) } @@ -165,6 +200,11 @@ func TestAddressEncoding(t *testing.T) { "02000102030405060708090a0b0c0d0e0f00010203", nil, }, + { + 21, + "03000102030405060708090a0b0c0d0e0f00010203", + nil, + }, } for no, test := range tests { data, _ := hex.DecodeString(test.hex) diff --git a/types/tx/errors.go b/types/tx/errors.go index c5e195efb..a05263e11 100644 --- a/types/tx/errors.go +++ b/types/tx/errors.go @@ -1,6 +1,13 @@ package tx -import "github.com/pactus-project/pactus/types/tx/payload" +import ( + "errors" + + "github.com/pactus-project/pactus/types/tx/payload" +) + +// ErrInvalidSigner is returned when the signer address is not valid. +var ErrInvalidSigner = errors.New("invalid signer address") // BasicCheckError is returned when the basic check on the transaction fails. type BasicCheckError struct { diff --git a/types/tx/tx.go b/types/tx/tx.go index 353087cd1..1e5f87456 100644 --- a/types/tx/tx.go +++ b/types/tx/tx.go @@ -8,6 +8,7 @@ import ( "github.com/fxamacker/cbor/v2" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/types/amount" "github.com/pactus-project/pactus/types/tx/payload" @@ -250,18 +251,37 @@ func (tx *Tx) UnmarshalCBOR(bs []byte) error { // SerializeSize returns the number of bytes it would take to serialize the transaction. func (tx *Tx) SerializeSize() int { - n := 3 + // one byte version, flag, payload type - 4 + // for tx.LockTime + n := 7 + // flag (1) + version (1) + payload type (1) + lock_time (4) encoding.VarIntSerializeSize(uint64(tx.Fee())) + encoding.VarStringSerializeSize(tx.Memo()) if tx.Payload() != nil { n += tx.Payload().SerializeSize() } if tx.data.Signature != nil { - n += bls.SignatureSize + switch tx.data.Payload.Signer().Type() { + case crypto.AddressTypeValidator, + crypto.AddressTypeBLSAccount: + n += bls.SignatureSize + + case crypto.AddressTypeEd25519Account: + n += ed25519.SignatureSize + + case crypto.AddressTypeTreasury: + n += 0 + } } if tx.data.PublicKey != nil { - n += bls.PublicKeySize + switch tx.data.Payload.Signer().Type() { + case crypto.AddressTypeValidator, + crypto.AddressTypeBLSAccount: + n += bls.PublicKeySize + + case crypto.AddressTypeEd25519Account: + n += ed25519.PublicKeySize + + case crypto.AddressTypeTreasury: + n += 0 + } } return n @@ -360,27 +380,74 @@ func (tx *Tx) Decode(r io.Reader) error { return err } - if !util.IsFlagSet(tx.data.Flags, flagNotSigned) { - sig := new(bls.Signature) - err = sig.Decode(r) + if util.IsFlagSet(tx.data.Flags, flagNotSigned) { + return nil + } + + // It is a signed transaction, Decode signatory. + sig, err := tx.decodeSignature(r) + if err != nil { + return err + } + tx.data.Signature = sig + + if !tx.IsPublicKeyStriped() { + pub, err := tx.decodePublicKey(r) if err != nil { return err } - tx.data.Signature = sig - - if !tx.IsPublicKeyStriped() { - pub := new(bls.PublicKey) - err = pub.Decode(r) - if err != nil { - return err - } - tx.data.PublicKey = pub - } + tx.data.PublicKey = pub } return nil } +func (tx *Tx) decodeSignature(r io.Reader) (crypto.Signature, error) { + switch tx.data.Payload.Signer().Type() { + case crypto.AddressTypeValidator, + crypto.AddressTypeBLSAccount: + sig := new(bls.Signature) + err := sig.Decode(r) + + return sig, err + + case crypto.AddressTypeEd25519Account: + sig := new(ed25519.Signature) + err := sig.Decode(r) + + return sig, err + + case crypto.AddressTypeTreasury: + return nil, ErrInvalidSigner + + default: + return nil, ErrInvalidSigner + } +} + +func (tx *Tx) decodePublicKey(r io.Reader) (crypto.PublicKey, error) { + switch tx.data.Payload.Signer().Type() { + case crypto.AddressTypeValidator, + crypto.AddressTypeBLSAccount: + pub := new(bls.PublicKey) + err := pub.Decode(r) + + return pub, err + + case crypto.AddressTypeEd25519Account: + pub := new(ed25519.PublicKey) + err := pub.Decode(r) + + return pub, err + + case crypto.AddressTypeTreasury: + return nil, ErrInvalidSigner + + default: + return nil, ErrInvalidSigner + } +} + func (tx *Tx) String() string { return fmt.Sprintf("{⌘ %v - %v 🏵 %v}", tx.ID().ShortString(), diff --git a/types/tx/tx_test.go b/types/tx/tx_test.go index 6dd3b4a26..b3893b775 100644 --- a/types/tx/tx_test.go +++ b/types/tx/tx_test.go @@ -7,8 +7,11 @@ import ( "testing" "github.com/fxamacker/cbor/v2" + "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/crypto/hash" + "github.com/pactus-project/pactus/types/amount" "github.com/pactus-project/pactus/types/tx" "github.com/pactus-project/pactus/types/tx/payload" "github.com/pactus-project/pactus/util" @@ -38,11 +41,6 @@ func TestEncodingTx(t *testing.T) { trx3 := ts.GenerateTestUnbondTx() trx4 := ts.GenerateTestWithdrawTx() trx5 := ts.GenerateTestSortitionTx() - assert.True(t, trx1.IsTransferTx()) - assert.True(t, trx2.IsBondTx()) - assert.True(t, trx3.IsUnbondTx()) - assert.True(t, trx4.IsWithdrawTx()) - assert.True(t, trx5.IsSortitionTx()) tests := []*tx.Tx{trx1, trx2, trx3, trx4, trx5} for _, trx := range tests { @@ -113,7 +111,7 @@ func TestBasicCheck(t *testing.T) { t.Run("Invalid payload, Should returns error", func(t *testing.T) { invAddr := ts.RandAccAddress() - invAddr[0] = 3 + invAddr[0] = 4 trx := tx.NewTransferTx(ts.RandHeight(), ts.RandAccAddress(), invAddr, 1e9, ts.RandAmount()) err := trx.BasicCheck() @@ -337,22 +335,22 @@ func TestInvalidSignature(t *testing.T) { }) } -func TestSignBytes(t *testing.T) { +func TestSignBytesBLS(t *testing.T) { d, _ := hex.DecodeString( "00" + // Flags "01" + // Version "01020304" + // LockTime "01" + // Fee - "00" + // Memo + "0474657374" + // Memo "01" + // PayloadType "013333333333333333333333333333333333333333" + // Sender "012222222222222222222222222222222222222222" + // Receiver - "01" + // Amount + "02" + // Amount "b53d79e156e9417e010fa21f2b2a96bee6be46fcd233295d2f697cdb9e782b6112ac01c80d0d9d64c2320664c77fa2a6" + // Signature "8d82fa4fcac04a3b565267685e90db1b01420285d2f8295683c138c092c209479983ba1591370778846681b7b558e061" + // PublicKey "1776208c0718006311c84b4a113335c70d1f5c7c5dd93a5625c4af51c48847abd0b590c055306162d2a03ca1cbf7bcc1") - h, _ := hash.FromString("1a8cedbb2ffce29df63210f112afb1c0295b27e2162323bfc774068f0573388e") + h, _ := hash.FromString("084f69979757cecb58d0a37bdd10eebee912ed29f923adb93f09d6bde2b94d5f") trx, err := tx.FromBytes(d) assert.NoError(t, err) assert.Equal(t, len(d), trx.SerializeSize()) @@ -362,6 +360,39 @@ func TestSignBytes(t *testing.T) { assert.Equal(t, h, trx.ID()) assert.Equal(t, hash.CalcHash(sb), trx.ID()) assert.Equal(t, uint32(0x04030201), trx.LockTime()) + assert.Equal(t, "test", trx.Memo()) + assert.Equal(t, amount.Amount(1), trx.Fee()) + assert.Equal(t, amount.Amount(2), trx.Payload().Value()) +} + +func TestSignBytesEd25519(t *testing.T) { + d, _ := hex.DecodeString( + "00" + // Flags + "01" + // Version + "01020304" + // LockTime + "01" + // Fee + "0474657374" + // Memo + "01" + // PayloadType + "033333333333333333333333333333333333333333" + // Sender + "032222222222222222222222222222222222222222" + // Receiver + "02" + // Amount + "4ed287f380291202f36a6a7516d602f1a6eaf789d092dd4050c0907ce79f49db" + // Signature + "6e70c21c82411803815db09713eab426297210a6793658d6bd9ed116ef2c0aac" + // PublicKey + "0aacf0da469a4a47dfb968a321ad7d6b919fdc37d2d2834c69cef90692730902") + + h, _ := hash.FromString("e5a0e1fb4ee6f26a867dd3c091fc9fdfcbd25a5caff8cf13a4485a716501150d") + trx, err := tx.FromBytes(d) + assert.NoError(t, err) + assert.Equal(t, len(d), trx.SerializeSize()) + + sb := d[1 : len(d)-ed25519.PublicKeySize-ed25519.SignatureSize] + assert.Equal(t, sb, trx.SignBytes()) + assert.Equal(t, h, trx.ID()) + assert.Equal(t, hash.CalcHash(sb), trx.ID()) + assert.Equal(t, uint32(0x04030201), trx.LockTime()) + assert.Equal(t, "test", trx.Memo()) + assert.Equal(t, amount.Amount(1), trx.Fee()) + assert.Equal(t, amount.Amount(2), trx.Payload().Value()) } func TestStripPublicKey(t *testing.T) { @@ -401,3 +432,51 @@ func TestFlagNotSigned(t *testing.T) { trx.SetSignature(nil) assert.False(t, trx.IsSigned(), "FlagNotSigned should not be set when the signature is set to nil") } + +func TestInvalidSignerSignature(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + trx := tx.NewTransferTx(ts.RandHeight(), crypto.TreasuryAddress, ts.RandAccAddress(), + ts.RandAmount(), ts.RandAmount()) + trx.SetSignature(ts.RandBLSSignature()) + + bytes, _ := trx.Bytes() + _, err := tx.FromBytes(bytes) + assert.ErrorIs(t, err, tx.ErrInvalidSigner) +} + +func TestInvalidSignerPublicKey(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + trx := tx.NewTransferTx(ts.RandHeight(), crypto.TreasuryAddress, ts.RandAccAddress(), + ts.RandAmount(), ts.RandAmount()) + pub, _ := ts.RandBLSKeyPair() + trx.SetSignature(ts.RandBLSSignature()) + trx.SetPublicKey(pub) + + bytes, _ := trx.Bytes() + _, err := tx.FromBytes(bytes) + assert.ErrorIs(t, err, tx.ErrInvalidSigner) +} + +func TestIsFreeTx(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + trx1 := ts.GenerateTestTransferTx() + trx2 := ts.GenerateTestBondTx() + trx3 := ts.GenerateTestUnbondTx() + trx4 := ts.GenerateTestWithdrawTx() + trx5 := ts.GenerateTestSortitionTx() + + assert.True(t, trx1.IsTransferTx()) + assert.True(t, trx2.IsBondTx()) + assert.True(t, trx3.IsUnbondTx()) + assert.True(t, trx4.IsWithdrawTx()) + assert.True(t, trx5.IsSortitionTx()) + + assert.False(t, trx1.IsFreeTx()) + assert.False(t, trx2.IsFreeTx()) + assert.True(t, trx3.IsFreeTx()) + assert.False(t, trx4.IsFreeTx()) + assert.True(t, trx5.IsFreeTx()) +} diff --git a/util/testsuite/testsuite.go b/util/testsuite/testsuite.go index 3ab7d7bfc..1b8237161 100644 --- a/util/testsuite/testsuite.go +++ b/util/testsuite/testsuite.go @@ -280,9 +280,12 @@ func (ts *TestSuite) RandHash() hash.Hash { // RandAccAddress generates a random account address for testing purposes. func (ts *TestSuite) RandAccAddress() crypto.Address { - addr := crypto.NewAddress(crypto.AddressTypeBLSAccount, ts.RandBytes(20)) + isBLSAddress := ts.RandBool() + if isBLSAddress { + return crypto.NewAddress(crypto.AddressTypeBLSAccount, ts.RandBytes(20)) + } - return addr + return crypto.NewAddress(crypto.AddressTypeEd25519Account, ts.RandBytes(20)) } // RandValAddress generates a random validator address for testing purposes. @@ -320,11 +323,11 @@ func (ts *TestSuite) RandPeerID() peer.ID { // GenerateTestAccount generates an account for testing purposes. func (ts *TestSuite) GenerateTestAccount(number int32) (*account.Account, crypto.Address) { - _, prv := ts.RandBLSKeyPair() + addr := ts.RandAccAddress() acc := account.NewAccount(number) acc.AddToBalance(ts.RandAmount()) - return acc, prv.PublicKeyNative().AccountAddress() + return acc, addr } // GenerateTestValidator generates a validator for testing purposes. diff --git a/wallet/vault/vault.go b/wallet/vault/vault.go index 6b928bc51..7dfe205d0 100644 --- a/wallet/vault/vault.go +++ b/wallet/vault/vault.go @@ -7,7 +7,9 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" - "github.com/pactus-project/pactus/crypto/bls/hdkeychain" + blshdkeychain "github.com/pactus-project/pactus/crypto/bls/hdkeychain" + "github.com/pactus-project/pactus/crypto/ed25519" + ed25519hdkeychain "github.com/pactus-project/pactus/crypto/ed25519/hdkeychain" "github.com/pactus-project/pactus/wallet/addresspath" "github.com/pactus-project/pactus/wallet/encrypter" "github.com/tyler-smith/go-bip39" @@ -15,25 +17,41 @@ import ( ) // -// Deterministic Hierarchy derivation path +// Deterministic Hierarchical Derivation Path // -// Specification +// Overview: // -// We define the following 4 levels in BIP32 path: +// This specification defines a hierarchical derivation path for generating addresses, based on BIP32. +// The path is structured into four distinct levels: // // m / purpose' / coin_type' / address_type' / address_index // -// Where: -// `'` Apostrophe in the path indicates that BIP32 hardened derivation is used. +// Explanation: +// // `m` Denotes the master node (or root) of the tree +// `'` Apostrophe in the path indicates that BIP32 hardened derivation is used. // `/` Separates the tree into depths, thus i / j signifies that j is a child of i -// `purpose` is set to 12381 which is the name of the new curve (BLS12-381). -// `coin_type` is set 21888 for Mainnet, 21777 for Testnet -// `address_type` determine the type of address -// `address_index` is a sequential number and increase when a new address is derived. +// +// Path Components: +// +// * `purpose`: Indicates the specific use case for the derived addresses: +// - 12381: Used for the BLS12-381 curve, based on PIP-8. +// - 65535: Used for imported private keys, based on PIP-13. +// - 44: A comprehensive purpose for standard curves, based on BIP-44. +// +// * `coin_type`: Identifies the coin type: +// - 21888: Pactus Mainnet +// - 21777: Pactus Testnet +// +// * `address_type`: Specifies the type of address. +// +// * `address_index`: A sequential number and increase when a new address is derived. // // References: -// PIP-8: https://pips.pactus.org/PIPs/pip-8 +// - https://pips.pactus.org/PIPs/pip-8 +// - https://pips.pactus.org/PIPs/pip-13 +// - https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki +// const ( TypeFull = int(1) @@ -49,6 +67,7 @@ type AddressInfo struct { const ( PurposeBLS12381 = uint32(12381) + PurposeBIP44 = uint32(44) PurposeImportPrivateKey = uint32(65535) ) @@ -71,7 +90,8 @@ type masterNode struct { } type purposes struct { - PurposeBLS purposeBLS `json:"purpose_bls"` // BLS Purpose: m/12381'/21888/0'/0' + PurposeBLS purposeBLS `json:"purpose_bls"` // BLS Purpose: m/12381'/21888'/1' or 2'/0 + PurposeEd25519 purposeEd25519 `json:"purpose_ed25519"` // ED25519 Purpose: m/44'/21888'/3'/0 } type purposeBLS struct { @@ -81,12 +101,16 @@ type purposeBLS struct { NextValidatorIndex uint32 `json:"next_validator_index"` // Index of next derived validator } +type purposeEd25519 struct { + NextAccountIndex uint32 `json:"next_account_index"` // Index of next derived account +} + func CreateVaultFromMnemonic(mnemonic string, coinType uint32) (*Vault, error) { seed, err := bip39.NewSeedWithErrorChecking(mnemonic, "") if err != nil { return nil, err } - masterKey, err := hdkeychain.NewMaster(seed, false) + masterKey, err := blshdkeychain.NewMaster(seed, false) if err != nil { return nil, err } @@ -396,31 +420,19 @@ func (v *Vault) PrivateKeys(password string, addrs []string) ([]crypto.PrivateKe switch path.Purpose() { case H(PurposeBLS12381): - seed, err := bip39.NewSeedWithErrorChecking(keyStore.MasterNode.Mnemonic, "") + prvKey, err := bls12381PrivateKey(keyStore, path) if err != nil { return nil, err } - masterKey, err := hdkeychain.NewMaster(seed, false) - if err != nil { - return nil, err - } - ext, err := masterKey.DerivePath(path) - if err != nil { - return nil, err - } - prvBytes, err := ext.RawPrivateKey() - if err != nil { - return nil, err - } - - prvKey, err := bls.PrivateKeyFromBytes(prvBytes) + keys[i] = prvKey + case H(PurposeBIP44): + prvKey, err := bip44PrivateKey(keyStore, path, password) if err != nil { return nil, err } - keys[i] = prvKey case H(PurposeImportPrivateKey): - index := path.AddressIndex() - hdkeychain.HardenedKeyStart + index := path.AddressIndex() - blshdkeychain.HardenedKeyStart // TODO: index out of range check str := keyStore.ImportedKeys[index] prv, err := bls.PrivateKeyFromString(str) @@ -437,7 +449,7 @@ func (v *Vault) PrivateKeys(password string, addrs []string) ([]crypto.PrivateKe } func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { - ext, err := hdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubAccount) + ext, err := blshdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubAccount) if err != nil { return nil, err } @@ -465,8 +477,53 @@ func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { return &data, nil } +func (v *Vault) NewEd25519AccountAddress(label, password string) (*AddressInfo, error) { + mnemonic, err := v.Mnemonic(password) + if err != nil { + return nil, err + } + + seed, err := bip39.NewSeedWithErrorChecking(mnemonic, password) + if err != nil { + return nil, err + } + + masterKey, err := ed25519hdkeychain.NewMaster(seed) + if err != nil { + return nil, err + } + + index := v.Purposes.PurposeEd25519.NextAccountIndex + ext, err := masterKey.DerivePath([]uint32{ + H(PurposeBIP44), + H(v.CoinType), + H(crypto.AddressTypeEd25519Account), + H(index), + }) + if err != nil { + return nil, err + } + + ed25519PubKey, err := ed25519.PublicKeyFromBytes(ext.RawPublicKey()) + if err != nil { + return nil, err + } + + addr := ed25519PubKey.AccountAddress().String() + data := AddressInfo{ + Address: addr, + Label: label, + PublicKey: ed25519PubKey.String(), + Path: addresspath.NewPath(ext.Path()...).String(), + } + v.Addresses[addr] = data + v.Purposes.PurposeEd25519.NextAccountIndex++ + + return &data, nil +} + func (v *Vault) NewValidatorAddress(label string) (*AddressInfo, error) { - ext, err := hdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubValidator) + ext, err := blshdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubValidator) if err != nil { return nil, err } @@ -527,7 +584,7 @@ func (v *Vault) AddressInfo(addr string) *AddressInfo { xPub = v.Purposes.PurposeBLS.XPubValidator } - ext, err := hdkeychain.NewKeyFromString(xPub) + ext, err := blshdkeychain.NewKeyFromString(xPub) if err != nil { return nil } @@ -548,6 +605,8 @@ func (v *Vault) AddressInfo(addr string) *AddressInfo { } info.PublicKey = blsPubKey.String() + case H(PurposeBIP44): + return &info case H(PurposeImportPrivateKey): default: return nil @@ -612,3 +671,42 @@ func (v *Vault) encryptKeyStore(keyStore *keyStore, password string) error { return nil } + +func bls12381PrivateKey(ks *keyStore, path []uint32) (*bls.PrivateKey, error) { + seed, err := bip39.NewSeedWithErrorChecking(ks.MasterNode.Mnemonic, "") + if err != nil { + return nil, err + } + masterKey, err := blshdkeychain.NewMaster(seed, false) + if err != nil { + return nil, err + } + ext, err := masterKey.DerivePath(path) + if err != nil { + return nil, err + } + prvBytes, err := ext.RawPrivateKey() + if err != nil { + return nil, err + } + + return bls.PrivateKeyFromBytes(prvBytes) +} + +func bip44PrivateKey(ks *keyStore, path []uint32, password string) (*ed25519.PrivateKey, error) { + seed, err := bip39.NewSeedWithErrorChecking(ks.MasterNode.Mnemonic, password) + if err != nil { + return nil, err + } + masterKey, err := ed25519hdkeychain.NewMaster(seed) + if err != nil { + return nil, err + } + ext, err := masterKey.DerivePath(path) + if err != nil { + return nil, err + } + prvBytes := ext.RawPrivateKey() + + return ed25519.PrivateKeyFromBytes(prvBytes) +} diff --git a/wallet/vault/vault_test.go b/wallet/vault/vault_test.go index 627b19428..7fc662bc5 100644 --- a/wallet/vault/vault_test.go +++ b/wallet/vault/vault_test.go @@ -231,6 +231,28 @@ func TestNewBLSAccountAddress(t *testing.T) { assert.Equal(t, label, addressInfo.Label) } +func TestNewED25519AccountAddress(t *testing.T) { + td := setup(t) + + addressInfo, err := td.vault.NewEd25519AccountAddress("addr-1", tPassword) + assert.NoError(t, err) + assert.NotEmpty(t, addressInfo.Address) + assert.NotEmpty(t, addressInfo.PublicKey) + assert.Equal(t, "m/44'/21888'/3'/0'", addressInfo.Path) + + addressInfo, err = td.vault.NewEd25519AccountAddress("addr-2", tPassword) + assert.NoError(t, err) + assert.NotEmpty(t, addressInfo.Address) + assert.NotEmpty(t, addressInfo.PublicKey) + assert.Equal(t, "m/44'/21888'/3'/1'", addressInfo.Path) + + addressInfo, err = td.vault.NewEd25519AccountAddress("addr-3", tPassword) + assert.NoError(t, err) + assert.NotEmpty(t, addressInfo.Address) + assert.NotEmpty(t, addressInfo.PublicKey) + assert.Equal(t, "m/44'/21888'/3'/2'", addressInfo.Path) +} + func TestNewValidatorAddress(t *testing.T) { td := setup(t) diff --git a/wallet/wallet.go b/wallet/wallet.go index ed54e7c71..ba6e3257f 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -19,8 +19,14 @@ import ( ) const ( - AddressTypeBLSAccount string = "bls_account" - AddressTypeValidator string = "validator" + AddressTypeBLSAccount string = "bls_account" + AddressTypeEd25519Account string = "ed25519_account" + AddressTypeValidator string = "validator" +) + +const ( + Version1 = 1 // initial version + Version2 = 2 // supporting Ed25519 = ) type Wallet struct { @@ -95,7 +101,7 @@ func Create(walletPath, mnemonic, password string, chain genesis.ChainType, opti } store := &store{ - Version: 1, + Version: Version2, UUID: uuid.New(), CreatedAt: time.Now().Round(time.Second).UTC(), Network: chain, @@ -402,6 +408,13 @@ func (w *Wallet) NewBLSAccountAddress(label string) (*vault.AddressInfo, error) return w.store.Vault.NewBLSAccountAddress(label) } +// NewEd25519AccountAddress create a new Ed25519-based account address and +// associates it with the given label. +// The password is required to access the master private key needed for address generation. +func (w *Wallet) NewEd25519AccountAddress(label, password string) (*vault.AddressInfo, error) { + return w.store.Vault.NewEd25519AccountAddress(label, password) +} + // NewValidatorAddress creates a new BLS validator address and // associates it with the given label. func (w *Wallet) NewValidatorAddress(label string) (*vault.AddressInfo, error) { diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 9704b91fc..53ebb25b1 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -257,7 +257,7 @@ func TestStake(t *testing.T) { }) } -func TestSigningTx(t *testing.T) { +func TestSigningTxWithBLS(t *testing.T) { td := setup(t) defer td.Close() @@ -286,6 +286,35 @@ func TestSigningTx(t *testing.T) { assert.Equal(t, fee, trx.Fee()) } +func TestSigningTxWithEd25519(t *testing.T) { + td := setup(t) + defer td.Close() + + senderInfo, _ := td.wallet.NewEd25519AccountAddress("testing addr", td.password) + receiver := td.RandAccAddress() + amt := td.RandAmount() + fee := td.RandFee() + lockTime := td.RandHeight() + + opts := []wallet.TxOption{ + wallet.OptionFee(fee), + wallet.OptionLockTime(lockTime), + wallet.OptionMemo("test"), + } + + trx, err := td.wallet.MakeTransferTx(senderInfo.Address, receiver.String(), amt, opts...) + assert.NoError(t, err) + err = td.wallet.SignTransaction(td.password, trx) + assert.NoError(t, err) + assert.NotNil(t, trx.Signature()) + assert.NoError(t, trx.BasicCheck()) + + id, err := td.wallet.BroadcastTransaction(trx) + assert.NoError(t, err) + assert.Equal(t, trx.ID().String(), id) + assert.Equal(t, fee, trx.Fee()) +} + func TestMakeTransferTx(t *testing.T) { td := setup(t) defer td.Close() From 0fd3ac211075b48abf8315e3a51d757c762066b3 Mon Sep 17 00:00:00 2001 From: Muhammad Javad Akbarian <94112796+akbariandev@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:58:28 +0330 Subject: [PATCH 19/25] feat(wallet): upgrade wallet (#1491) Co-authored-by: mj --- cmd/wallet/address.go | 2 +- wallet/errors.go | 13 +- wallet/store.go | 119 ++++++++++++++-- wallet/store_test.go | 38 +++++ wallet/testdata/unsupported_wallet | 3 + wallet/testdata/wallet_version_1 | 59 ++++++++ wallet/vault/vault.go | 215 ++++++++++------------------- wallet/vault/vault_test.go | 131 +++++++++--------- wallet/wallet.go | 34 +++-- wallet/wallet_test.go | 10 +- 10 files changed, 390 insertions(+), 234 deletions(-) create mode 100644 wallet/store_test.go create mode 100644 wallet/testdata/unsupported_wallet create mode 100644 wallet/testdata/wallet_version_1 diff --git a/cmd/wallet/address.go b/cmd/wallet/address.go index 1134e520a..64fc24831 100644 --- a/cmd/wallet/address.go +++ b/cmd/wallet/address.go @@ -204,7 +204,7 @@ func buildImportPrivateKeyCmd(parentCmd *cobra.Command) { cmd.FatalErrorCheck(err) password := getPassword(wlt, *passOpt) - err = wlt.ImportPrivateKey(password, prv) + err = wlt.ImportBLSPrivateKey(password, prv) cmd.FatalErrorCheck(err) err = wlt.Save() diff --git a/wallet/errors.go b/wallet/errors.go index 9036a41c4..6d9b3f525 100644 --- a/wallet/errors.go +++ b/wallet/errors.go @@ -17,7 +17,7 @@ var ( ErrHistoryExists = errors.New("transaction already exists") ) -// CRCNotMatchError describes an error in which the wallet CRC is not macthed. +// CRCNotMatchError describes an error in which the wallet CRC is not matched. type CRCNotMatchError struct { Expected uint32 Got uint32 @@ -36,3 +36,14 @@ type ExitsError struct { func (e ExitsError) Error() string { return fmt.Sprintf("a wallet exists at: %s", e.Path) } + +// UnsupportedVersionError indicates the wallet version is incompatible with the software's supported version. +type UnsupportedVersionError struct { + WalletVersion int + SupportedVersion int +} + +func (e UnsupportedVersionError) Error() string { + return fmt.Sprintf("wallet version %d is not supported, latest supported version is %d", + e.WalletVersion, e.SupportedVersion) +} diff --git a/wallet/store.go b/wallet/store.go index c56a03c19..452f1e1d6 100644 --- a/wallet/store.go +++ b/wallet/store.go @@ -2,15 +2,29 @@ package wallet import ( "encoding/json" + "fmt" "hash/crc32" "time" "github.com/google/uuid" + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/crypto/bls" + blshdkeychain "github.com/pactus-project/pactus/crypto/bls/hdkeychain" "github.com/pactus-project/pactus/genesis" + "github.com/pactus-project/pactus/util" + "github.com/pactus-project/pactus/util/logger" + "github.com/pactus-project/pactus/wallet/addresspath" "github.com/pactus-project/pactus/wallet/vault" ) -type store struct { +const ( + Version1 = 1 // initial version + Version2 = 2 // supporting Ed25519 + + VersionLatest = Version2 +) + +type Store struct { Version int `json:"version"` UUID uuid.UUID `json:"uuid"` CreatedAt time.Time `json:"created_at"` @@ -20,18 +34,22 @@ type store struct { History history `json:"history"` } -func (s *store) ToBytes() ([]byte, error) { +func FromBytes(data []byte) (*Store, error) { + s := new(Store) + if err := json.Unmarshal(data, s); err != nil { + return nil, err + } + + return s, nil +} + +func (s *Store) ToBytes() ([]byte, error) { s.VaultCRC = s.calcVaultCRC() return json.MarshalIndent(s, " ", " ") } -func (s *store) Save(bs []byte) error { - err := json.Unmarshal(bs, s) - if err != nil { - return err - } - +func (s *Store) ValidateCRC() error { crc := s.calcVaultCRC() if s.VaultCRC != crc { return CRCNotMatchError{ @@ -43,7 +61,90 @@ func (s *store) Save(bs []byte) error { return nil } -func (s *store) calcVaultCRC() uint32 { +func (s *Store) UpgradeWallet(walletPath string) error { + oldVersion := s.Version + switch oldVersion { + case Version1: + if err := s.setPublicKeys(); err != nil { + return err + } + + case Version2: + // Current version + return nil + + default: + return UnsupportedVersionError{ + WalletVersion: s.Version, + SupportedVersion: VersionLatest, + } + } + + s.VaultCRC = s.calcVaultCRC() + s.Version = Version2 + + bs, err := s.ToBytes() + if err != nil { + return err + } + + err = util.WriteFile(walletPath, bs) + if err != nil { + return err + } + logger.Info(fmt.Sprintf("wallet upgraded from version %d to version %d", + oldVersion, VersionLatest)) + + return nil +} + +func (s *Store) setPublicKeys() error { + for addrKey, info := range s.Vault.Addresses { + if info.PublicKey != "" { + continue + } + + // Some old wallet doesn't have public key for all addresses. + addr, err := crypto.AddressFromString(info.Address) + if err != nil { + return err + } + + var xPub string + if addr.IsAccountAddress() { + xPub = s.Vault.Purposes.PurposeBLS.XPubAccount + } else if addr.IsValidatorAddress() { + xPub = s.Vault.Purposes.PurposeBLS.XPubValidator + } + + ext, err := blshdkeychain.NewKeyFromString(xPub) + if err != nil { + return err + } + + p, err := addresspath.FromString(info.Path) + if err != nil { + return err + } + + extendedKey, err := ext.Derive(p.AddressIndex()) + if err != nil { + return err + } + + blsPubKey, err := bls.PublicKeyFromBytes(extendedKey.RawPublicKey()) + if err != nil { + return err + } + + info.PublicKey = blsPubKey.String() + s.Vault.Addresses[addrKey] = info + } + + return nil +} + +func (s *Store) calcVaultCRC() uint32 { d, err := json.Marshal(s.Vault) if err != nil { return 0 diff --git a/wallet/store_test.go b/wallet/store_test.go new file mode 100644 index 000000000..2c0785e2a --- /dev/null +++ b/wallet/store_test.go @@ -0,0 +1,38 @@ +package wallet + +import ( + "testing" + + "github.com/pactus-project/pactus/util" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUpgradeWallet(t *testing.T) { + // password is: "password" + data, err := util.ReadFile("./testdata/wallet_version_1") + require.NoError(t, err) + + tempPath := util.TempFilePath() + err = util.WriteFile(tempPath, data) + require.NoError(t, err) + + wlt, err := Open(tempPath, true) + require.NoError(t, err) + + assert.Equal(t, 4, wlt.AddressCount()) + assert.Equal(t, VersionLatest, wlt.store.Version) + + infos := wlt.AddressInfos() + for _, info := range infos { + assert.NotEmpty(t, info.PublicKey) + } +} + +func TestUnsupportedWallet(t *testing.T) { + _, err := Open("./testdata/unsupported_wallet", true) + require.ErrorIs(t, err, UnsupportedVersionError{ + WalletVersion: 3, + SupportedVersion: VersionLatest, + }) +} diff --git a/wallet/testdata/unsupported_wallet b/wallet/testdata/unsupported_wallet new file mode 100644 index 000000000..cd2f236b2 --- /dev/null +++ b/wallet/testdata/unsupported_wallet @@ -0,0 +1,3 @@ +{ + "version": 3 +} diff --git a/wallet/testdata/wallet_version_1 b/wallet/testdata/wallet_version_1 new file mode 100644 index 000000000..30b170ee7 --- /dev/null +++ b/wallet/testdata/wallet_version_1 @@ -0,0 +1,59 @@ +{ + "version": 1, + "uuid": "44156117-268a-49f0-a906-400659b7a051", + "created_at": "2024-08-27T16:45:08Z", + "network": 0, + "crc": 885152871, + "vault": { + "type": 1, + "coin_type": 21888, + "addresses": { + "pc1p4xuja689hg2434yhr32clhn97x6afw58qlrcyd": { + "address": "pc1p4xuja689hg2434yhr32clhn97x6afw58qlrcyd", + "public_key": "public1p3wmdecume03kehtcaks95jjyem2m7pev0da2yx7t0gws66nkgp7vaah5sdd5gv0s4d34y0nqxch0cqq7fnsy9v46kum7e46gx9dua4sss7ne57m5c776h0e9dt0dw8hv24uushps9arv0zk8dc2xe0k7pgk588tf", + "label": "Imported Validator Address 1", + "path": "m/65535'/21888'/1'/0'" + }, + "pc1pjneygutecly9gtandrdt8j36v8g4fl42k4y5xp": { + "address": "pc1pjneygutecly9gtandrdt8j36v8g4fl42k4y5xp", + "public_key": "", + "label": "test-2", + "path": "m/12381'/21888'/1'/0" + }, + "pc1z0m0vw8sjfgv7f2zgq2hfxutg8rwn7gpffhe8tf": { + "address": "pc1z0m0vw8sjfgv7f2zgq2hfxutg8rwn7gpffhe8tf", + "public_key": "", + "label": "test-1", + "path": "m/12381'/21888'/2'/0" + }, + "pc1z4xuja689hg2434yhr32clhn97x6afw58a5n9ns": { + "address": "pc1z4xuja689hg2434yhr32clhn97x6afw58a5n9ns", + "public_key": "public1p3wmdecume03kehtcaks95jjyem2m7pev0da2yx7t0gws66nkgp7vaah5sdd5gv0s4d34y0nqxch0cqq7fnsy9v46kum7e46gx9dua4sss7ne57m5c776h0e9dt0dw8hv24uushps9arv0zk8dc2xe0k7pgk588tf", + "label": "Imported Reward Address 1", + "path": "m/65535'/21888'/2'/0'" + } + }, + "encrypter": { + "method": "ARGON2ID-AES_256_CTR-MACV1", + "params": { + "iterations": "3", + "memory": "65536", + "parallelism": "4" + } + }, + "key_store": "hlkOogftrz0kU1xqwIF4Vgj5/fuo+6FNSUWK+cVD20Fvrp1KUUNQTDex9F5SC/EMJfoJhwH5ofMek+j9bDYJL53BX5wO3w/ASqm/+j23cm6VJ40IMh+q74OX3pNOTMvSd9ZDYO0aPEA4rnKLyBMHX2L82r0DaAfLQ8zNV+ngx+SUCBPy+cpvzyoHdvYDlwf1YdSjjrbBfLaXa53Odg38Zgp9eieJb3gcq51jtM5GOOpXb1YR9jByYBb/7cn75/1WoEkojRCcylK/+/SYdCnGhsXbpVPu4/70LaPKDa+JNBytq1Kg", + "purposes": { + "purpose_bls": { + "xpub_account": "xpublic1pqdwnqqyqsp2spqqpqqqgqgxj6mlduay8ase6hkefwa2lk2esz0gn2yu59tnk3w2tgnlfk5hleuqxpqdlt5q2f207qrwq9gasqscpckjv8hggc57n044gvml7u05cpzu8ra0zq2s3x3mak6xhtzga27tdx5pypnqxhlkf9aedptzcsd8l3q6m7ch6g4lphzsdv20fvc3dsu7mlj8kdy3n5fyllg07wecmpr8y6nsr95zlz", + "xpub_validator": "xpublic1pqdwnqqyqsp2spqqzqqqgqgx4n38q9n6qtvgrnx5r8atntrfnj4thwj6my5tx8tfe6ex6p89y7qqxptrfzgmnu62rut65lddgxl5nujdn82tusz5w2wqpjqpdpgplj0zx3gaaz9wv93yqcls6clepehlvhsvdp2ndwphhmag3j3hgsfxxz434hduxvqq4n8njxh4x9mnal2wma4sw5kp6y680tkut62gk6trfjscmsdumc", + "next_account_index": 1, + "next_validator_index": 1 + } + } + }, + "history": { + "transactions": null, + "activities": null, + "pendings": null + } +} diff --git a/wallet/vault/vault.go b/wallet/vault/vault.go index 7dfe205d0..81ee3e5ed 100644 --- a/wallet/vault/vault.go +++ b/wallet/vault/vault.go @@ -90,19 +90,19 @@ type masterNode struct { } type purposes struct { - PurposeBLS purposeBLS `json:"purpose_bls"` // BLS Purpose: m/12381'/21888'/1' or 2'/0 - PurposeEd25519 purposeEd25519 `json:"purpose_ed25519"` // ED25519 Purpose: m/44'/21888'/3'/0 + PurposeBLS purposeBLS `json:"purpose_bls"` // BLS Purpose: m/12381'/21888'/1' or 2'/0 + PurposeBIP44 purposeBIP44 `json:"purpose_bip44"` // BIP44 Purpose: m/44'/21888'/3'/0' } type purposeBLS struct { - XPubValidator string `json:"xpub_account"` // Extended public key for account: m/12381'/21888/1'/0 - XPubAccount string `json:"xpub_validator"` // Extended public key for validator: m/12381'/218 + XPubValidator string `json:"xpub_account"` // Extended public key for account: m/12381'/21888'/1'/0 + XPubAccount string `json:"xpub_validator"` // Extended public key for validator: m/12381'/21888'/2'/0 NextAccountIndex uint32 `json:"next_account_index"` // Index of next derived account NextValidatorIndex uint32 `json:"next_validator_index"` // Index of next derived validator } -type purposeEd25519 struct { - NextAccountIndex uint32 `json:"next_account_index"` // Index of next derived account +type purposeBIP44 struct { + NextEd25519Index uint32 `json:"next_ed25519_index"` // Index of next Ed25519 derived account: m/44'/21888/3'/0' } func CreateVaultFromMnemonic(mnemonic string, coinType uint32) (*Vault, error) { @@ -331,7 +331,7 @@ func (v *Vault) AddressFromPath(p string) *AddressInfo { return nil } -func (v *Vault) ImportPrivateKey(password string, prv *bls.PrivateKey) error { +func (v *Vault) ImportBLSPrivateKey(password string, prv *bls.PrivateKey) error { if v.IsNeutered() { return ErrNeutered } @@ -342,7 +342,6 @@ func (v *Vault) ImportPrivateKey(password string, prv *bls.PrivateKey) error { } addressIndex := len(keyStore.ImportedKeys) - pub := prv.PublicKeyNative() accAddr := pub.AccountAddress() @@ -371,7 +370,7 @@ func (v *Vault) ImportPrivateKey(password string, prv *bls.PrivateKey) error { v.Addresses[accAddr.String()] = AddressInfo{ Address: accAddr.String(), PublicKey: pub.String(), - Label: fmt.Sprintf("Imported Reward Address %d", importedPrvLabelCounter), + Label: fmt.Sprintf("Imported BLS Account Address %d", importedPrvLabelCounter), Path: blsAccPathStr, } @@ -392,15 +391,18 @@ func (v *Vault) ImportPrivateKey(password string, prv *bls.PrivateKey) error { return nil } +// PrivateKeys retrieves the private keys for the given addresses using the provided password. func (v *Vault) PrivateKeys(password string, addrs []string) ([]crypto.PrivateKey, error) { if v.IsNeutered() { return nil, ErrNeutered } + // Decrypt the key store once to avoid decrypting for each key. keyStore, err := v.decryptKeyStore(password) if err != nil { return nil, err } + mnemonicSeed := bip39.NewSeed(keyStore.MasterNode.Mnemonic, "") keys := make([]crypto.PrivateKey, len(addrs)) for i, addr := range addrs { @@ -409,31 +411,31 @@ func (v *Vault) PrivateKeys(password string, addrs []string) ([]crypto.PrivateKe return nil, NewErrAddressNotFound(addr) } - path, err := addresspath.FromString(info.Path) + hdPath, err := addresspath.FromString(info.Path) if err != nil { return nil, err } - if path.CoinType() != H(v.CoinType) { + if hdPath.CoinType() != H(v.CoinType) { return nil, ErrInvalidCoinType } - switch path.Purpose() { + switch hdPath.Purpose() { case H(PurposeBLS12381): - prvKey, err := bls12381PrivateKey(keyStore, path) + prvKey, err := v.deriveBLSPrivateKey(mnemonicSeed, hdPath) if err != nil { return nil, err } keys[i] = prvKey case H(PurposeBIP44): - prvKey, err := bip44PrivateKey(keyStore, path, password) + prvKey, err := v.deriveEd25519PrivateKey(mnemonicSeed, hdPath) if err != nil { return nil, err } keys[i] = prvKey case H(PurposeImportPrivateKey): - index := path.AddressIndex() - blshdkeychain.HardenedKeyStart - // TODO: index out of range check + index := hdPath.AddressIndex() - blshdkeychain.HardenedKeyStart + // TODO: Check if index is within the valid range. str := keyStore.ImportedKeys[index] prv, err := bls.PrivateKeyFromString(str) if err != nil { @@ -448,6 +450,35 @@ func (v *Vault) PrivateKeys(password string, addrs []string) ([]crypto.PrivateKe return keys, nil } +func (v *Vault) NewValidatorAddress(label string) (*AddressInfo, error) { + ext, err := blshdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubValidator) + if err != nil { + return nil, err + } + index := v.Purposes.PurposeBLS.NextValidatorIndex + ext, err = ext.DerivePath([]uint32{index}) + if err != nil { + return nil, err + } + + blsPubKey, err := bls.PublicKeyFromBytes(ext.RawPublicKey()) + if err != nil { + return nil, err + } + + addr := blsPubKey.ValidatorAddress().String() + info := AddressInfo{ + Address: addr, + Label: label, + PublicKey: blsPubKey.String(), + Path: addresspath.NewPath(ext.Path()...).String(), + } + v.Addresses[addr] = info + v.Purposes.PurposeBLS.NextValidatorIndex++ + + return &info, nil +} + func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { ext, err := blshdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubAccount) if err != nil { @@ -465,25 +496,20 @@ func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { } addr := blsPubKey.AccountAddress().String() - data := AddressInfo{ + info := AddressInfo{ Address: addr, Label: label, PublicKey: blsPubKey.String(), Path: addresspath.NewPath(ext.Path()...).String(), } - v.Addresses[addr] = data + v.Addresses[addr] = info v.Purposes.PurposeBLS.NextAccountIndex++ - return &data, nil + return &info, nil } func (v *Vault) NewEd25519AccountAddress(label, password string) (*AddressInfo, error) { - mnemonic, err := v.Mnemonic(password) - if err != nil { - return nil, err - } - - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, password) + seed, err := v.MnemonicSeed(password) if err != nil { return nil, err } @@ -493,7 +519,7 @@ func (v *Vault) NewEd25519AccountAddress(label, password string) (*AddressInfo, return nil, err } - index := v.Purposes.PurposeEd25519.NextAccountIndex + index := v.Purposes.PurposeBIP44.NextEd25519Index ext, err := masterKey.DerivePath([]uint32{ H(PurposeBIP44), H(v.CoinType), @@ -510,49 +536,18 @@ func (v *Vault) NewEd25519AccountAddress(label, password string) (*AddressInfo, } addr := ed25519PubKey.AccountAddress().String() - data := AddressInfo{ + info := AddressInfo{ Address: addr, Label: label, PublicKey: ed25519PubKey.String(), Path: addresspath.NewPath(ext.Path()...).String(), } - v.Addresses[addr] = data - v.Purposes.PurposeEd25519.NextAccountIndex++ - - return &data, nil -} - -func (v *Vault) NewValidatorAddress(label string) (*AddressInfo, error) { - ext, err := blshdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubValidator) - if err != nil { - return nil, err - } - index := v.Purposes.PurposeBLS.NextValidatorIndex - ext, err = ext.DerivePath([]uint32{index}) - if err != nil { - return nil, err - } - - blsPubKey, err := bls.PublicKeyFromBytes(ext.RawPublicKey()) - if err != nil { - return nil, err - } - - addr := blsPubKey.ValidatorAddress().String() - data := AddressInfo{ - Address: addr, - Label: label, - PublicKey: blsPubKey.String(), - Path: addresspath.NewPath(ext.Path()...).String(), - } - v.Addresses[addr] = data - v.Purposes.PurposeBLS.NextValidatorIndex++ + v.Addresses[addr] = info + v.Purposes.PurposeBIP44.NextEd25519Index++ - return &data, nil + return &info, nil } -// TODO change structure of AddressInfo to more informatively object - // AddressInfo like it can return bls.PublicKey instead of string. func (v *Vault) AddressInfo(addr string) *AddressInfo { info, ok := v.Addresses[addr] @@ -560,58 +555,6 @@ func (v *Vault) AddressInfo(addr string) *AddressInfo { return nil } - path, err := addresspath.FromString(info.Path) - if err != nil { - return nil - } - - // TODO it would be better to return error in future - if path.CoinType() != H(v.CoinType) { - return nil - } - - switch path.Purpose() { - case H(PurposeBLS12381): - addr, err := crypto.AddressFromString(info.Address) - if err != nil { - return nil - } - - var xPub string - if addr.IsAccountAddress() { - xPub = v.Purposes.PurposeBLS.XPubAccount - } else if addr.IsValidatorAddress() { - xPub = v.Purposes.PurposeBLS.XPubValidator - } - - ext, err := blshdkeychain.NewKeyFromString(xPub) - if err != nil { - return nil - } - - p, err := addresspath.FromString(info.Path) - if err != nil { - return nil - } - - extendedKey, err := ext.Derive(p.AddressIndex()) - if err != nil { - return nil - } - - blsPubKey, err := bls.PublicKeyFromBytes(extendedKey.RawPublicKey()) - if err != nil { - return nil - } - - info.PublicKey = blsPubKey.String() - case H(PurposeBIP44): - return &info - case H(PurposeImportPrivateKey): - default: - return nil - } - return &info } @@ -620,9 +563,6 @@ func (v *Vault) Contains(addr string) bool { } func (v *Vault) Mnemonic(password string) (string, error) { - if v.IsNeutered() { - return "", ErrNeutered - } keyStore, err := v.decryptKeyStore(password) if err != nil { return "", err @@ -631,7 +571,21 @@ func (v *Vault) Mnemonic(password string) (string, error) { return keyStore.MasterNode.Mnemonic, nil } +func (v *Vault) MnemonicSeed(password string) ([]byte, error) { + mnemonic, err := v.Mnemonic(password) + if err != nil { + return nil, err + } + seed := bip39.NewSeed(mnemonic, "") + + return seed, nil +} + func (v *Vault) decryptKeyStore(password string) (*keyStore, error) { + if v.IsNeutered() { + return nil, ErrNeutered + } + keyStoreData, err := v.Encrypter.Decrypt(v.KeyStore, password) if err != nil { return nil, err @@ -640,18 +594,7 @@ func (v *Vault) decryptKeyStore(password string) (*keyStore, error) { keyStore := new(keyStore) err = json.Unmarshal([]byte(keyStoreData), keyStore) if err != nil { - // _oldKeyStore is temporary struct which supports wallet structure - // of old users that still didn't update their wallets. it automatically will update to new structure. - type _oldKeyStore struct { - MasterNode masterNode `json:"master_node"` // HD Root Tree (Master node) - ImportedKeys map[string]string `json:"imported_keys"` // Imported private keys - } - - oldKeyStore := new(_oldKeyStore) - if err := json.Unmarshal([]byte(keyStoreData), oldKeyStore); err != nil { - return nil, err - } - keyStore.MasterNode = oldKeyStore.MasterNode + return nil, err } return keyStore, nil @@ -672,12 +615,8 @@ func (v *Vault) encryptKeyStore(keyStore *keyStore, password string) error { return nil } -func bls12381PrivateKey(ks *keyStore, path []uint32) (*bls.PrivateKey, error) { - seed, err := bip39.NewSeedWithErrorChecking(ks.MasterNode.Mnemonic, "") - if err != nil { - return nil, err - } - masterKey, err := blshdkeychain.NewMaster(seed, false) +func (*Vault) deriveBLSPrivateKey(mnemonicSeed []byte, path []uint32) (*bls.PrivateKey, error) { + masterKey, err := blshdkeychain.NewMaster(mnemonicSeed, false) if err != nil { return nil, err } @@ -693,12 +632,8 @@ func bls12381PrivateKey(ks *keyStore, path []uint32) (*bls.PrivateKey, error) { return bls.PrivateKeyFromBytes(prvBytes) } -func bip44PrivateKey(ks *keyStore, path []uint32, password string) (*ed25519.PrivateKey, error) { - seed, err := bip39.NewSeedWithErrorChecking(ks.MasterNode.Mnemonic, password) - if err != nil { - return nil, err - } - masterKey, err := ed25519hdkeychain.NewMaster(seed) +func (*Vault) deriveEd25519PrivateKey(mnemonicSeed []byte, path []uint32) (*ed25519.PrivateKey, error) { + masterKey, err := ed25519hdkeychain.NewMaster(mnemonicSeed) if err != nil { return nil, err } diff --git a/wallet/vault/vault_test.go b/wallet/vault/vault_test.go index 7fc662bc5..a2e7e01e4 100644 --- a/wallet/vault/vault_test.go +++ b/wallet/vault/vault_test.go @@ -8,6 +8,7 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/bls/hdkeychain" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/util/testsuite" "github.com/pactus-project/pactus/wallet/addresspath" "github.com/pactus-project/pactus/wallet/encrypter" @@ -40,16 +41,14 @@ func setup(t *testing.T) *testData { assert.False(t, key.IsPrivate()) // Create some test address - _, err = vault.NewBLSAccountAddress("addr-1") + _, err = vault.NewBLSAccountAddress("bls-account-address") assert.NoError(t, err) - _, err = vault.NewBLSAccountAddress("addr-2") + _, err = vault.NewEd25519AccountAddress("ed25519-account-address", "") assert.NoError(t, err) - _, err = vault.NewValidatorAddress("addr-3") - assert.NoError(t, err) - _, err = vault.NewValidatorAddress("addr-4") + _, err = vault.NewValidatorAddress("validator-address") assert.NoError(t, err) - assert.NoError(t, vault.ImportPrivateKey("", importedPrv)) + assert.NoError(t, vault.ImportBLSPrivateKey("", importedPrv)) assert.False(t, vault.IsEncrypted()) opts := []encrypter.Option{ @@ -73,13 +72,10 @@ func setup(t *testing.T) *testData { func TestAddressInfo(t *testing.T) { td := setup(t) - assert.Equal(t, td.vault.AddressCount(), 6) + assert.Equal(t, td.vault.AddressCount(), 5) infos := td.vault.AddressInfos() for _, i := range infos { info := td.vault.AddressInfo(i.Address) - assert.Equal(t, i.Address, info.Address) - // TODO test me later - // assert.Equal(t, i.Address, info.PublicKey) addr, _ := crypto.AddressFromString(info.Address) path, _ := addresspath.FromString(info.Path) @@ -87,47 +83,54 @@ func TestAddressInfo(t *testing.T) { switch path.Purpose() { case H(PurposeBLS12381): if addr.IsValidatorAddress() { - assert.Equal(t, fmt.Sprintf("m/%d'/%d'/1'/%d", - PurposeBLS12381, td.vault.CoinType, path.AddressIndex()), info.Path) + assert.Equal(t, fmt.Sprintf("m/12381'/%d'/1'/%d", + td.vault.CoinType, path.AddressIndex()), info.Path) } if addr.IsAccountAddress() { - assert.Equal(t, fmt.Sprintf("m/%d'/%d'/2'/%d", - PurposeBLS12381, td.vault.CoinType, path.AddressIndex()), info.Path) + assert.Equal(t, fmt.Sprintf("m/12381'/%d'/2'/%d", + td.vault.CoinType, path.AddressIndex()), info.Path) } + case H(PurposeBIP44): + assert.Equal(t, fmt.Sprintf("m/44'/%d'/3'/%d'", + td.vault.CoinType, path.AddressIndex()-addresspath.HardenedKeyStart), info.Path) + case H(PurposeImportPrivateKey): if addr.IsValidatorAddress() { - assert.Equal(t, fmt.Sprintf("m/%d'/%d'/1'/%d'", - PurposeImportPrivateKey, td.vault.CoinType, path.AddressIndex()-hdkeychain.HardenedKeyStart), info.Path) + assert.Equal(t, fmt.Sprintf("m/65535'/%d'/1'/%d'", + td.vault.CoinType, path.AddressIndex()-hdkeychain.HardenedKeyStart), info.Path) } if addr.IsAccountAddress() { - assert.Equal(t, fmt.Sprintf("m/%d'/%d'/2'/%d'", - PurposeImportPrivateKey, td.vault.CoinType, path.AddressIndex()-hdkeychain.HardenedKeyStart), info.Path) + assert.Equal(t, fmt.Sprintf("m/65535'/%d'/2'/%d'", + td.vault.CoinType, path.AddressIndex()-hdkeychain.HardenedKeyStart), info.Path) } + + default: + assert.Fail(t, "not supported") } } // Neutered neutered := td.vault.Neuter() - assert.Equal(t, 6, neutered.AddressCount()) + assert.Equal(t, 5, neutered.AddressCount()) } func TestSortAddressInfo(t *testing.T) { td := setup(t) - assert.Equal(t, 6, td.vault.AddressCount()) infos := td.vault.AddressInfos() - assert.Equal(t, "m/12381'/21888'/1'/0", infos[0].Path) - assert.Equal(t, "m/65535'/21888'/2'/0'", infos[len(infos)-1].Path) + assert.Equal(t, "m/44'/21888'/3'/0'", infos[0].Path) + assert.Equal(t, "m/12381'/21888'/1'/0", infos[1].Path) + assert.Equal(t, "m/12381'/21888'/2'/0", infos[2].Path) + assert.Equal(t, "m/65535'/21888'/1'/0'", infos[3].Path) + assert.Equal(t, "m/65535'/21888'/2'/0'", infos[4].Path) } func TestAllAccountAddresses(t *testing.T) { td := setup(t) - assert.Equal(t, td.vault.AddressCount(), 6) - accountAddrs := td.vault.AllAccountAddresses() for _, i := range accountAddrs { path, err := addresspath.FromString(i.Path) @@ -140,8 +143,6 @@ func TestAllAccountAddresses(t *testing.T) { func TestAllValidatorAddresses(t *testing.T) { td := setup(t) - assert.Equal(t, 6, td.vault.AddressCount()) - validatorAddrs := td.vault.AllValidatorAddresses() for _, i := range validatorAddrs { info := td.vault.AddressInfo(i.Address) @@ -156,6 +157,8 @@ func TestAllValidatorAddresses(t *testing.T) { case H(PurposeImportPrivateKey): assert.Equal(t, fmt.Sprintf("m/%d'/%d'/1'/%d'", PurposeImportPrivateKey, td.vault.CoinType, path.AddressIndex()-hdkeychain.HardenedKeyStart), info.Path) + default: + assert.Fail(t, "not supported") } } } @@ -163,7 +166,6 @@ func TestAllValidatorAddresses(t *testing.T) { func TestSortAllValidatorAddresses(t *testing.T) { td := setup(t) - assert.Equal(t, td.vault.AddressCount(), 6) validatorAddrs := td.vault.AllValidatorAddresses() assert.Equal(t, "m/12381'/21888'/1'/0", validatorAddrs[0].Path) @@ -172,7 +174,6 @@ func TestSortAllValidatorAddresses(t *testing.T) { func TestAddressFromPath(t *testing.T) { td := setup(t) - assert.Equal(t, td.vault.AddressCount(), 6) t.Run("Could not find address from path", func(t *testing.T) { path := "m/12381'/26888'/983'/0" @@ -197,8 +198,6 @@ func TestAddressFromPath(t *testing.T) { func TestAllImportedPrivateKeysAddresses(t *testing.T) { td := setup(t) - assert.Equal(t, td.vault.AddressCount(), 6) - importedPrvAddrs := td.vault.AllImportedPrivateKeysAddresses() for _, i := range importedPrvAddrs { info := td.vault.AddressInfo(i.Address) @@ -219,50 +218,47 @@ func TestAllImportedPrivateKeysAddresses(t *testing.T) { } } -func TestNewBLSAccountAddress(t *testing.T) { +func TestNewValidatorAddress(t *testing.T) { td := setup(t) label := td.RandString(16) - addressInfo, err := td.vault.NewBLSAccountAddress(label) + addressInfo, err := td.vault.NewValidatorAddress(label) assert.NoError(t, err) assert.NotEmpty(t, addressInfo.Address) assert.NotEmpty(t, addressInfo.PublicKey) - assert.Contains(t, addressInfo.Path, "m/12381'/21888'/2'") + assert.Contains(t, addressInfo.Path, "m/12381'/21888'/1'") assert.Equal(t, label, addressInfo.Label) + + pub, _ := bls.PublicKeyFromString(addressInfo.PublicKey) + assert.Equal(t, pub.ValidatorAddress().String(), addressInfo.Address) } -func TestNewED25519AccountAddress(t *testing.T) { +func TestNewBLSAccountAddress(t *testing.T) { td := setup(t) - addressInfo, err := td.vault.NewEd25519AccountAddress("addr-1", tPassword) - assert.NoError(t, err) - assert.NotEmpty(t, addressInfo.Address) - assert.NotEmpty(t, addressInfo.PublicKey) - assert.Equal(t, "m/44'/21888'/3'/0'", addressInfo.Path) - - addressInfo, err = td.vault.NewEd25519AccountAddress("addr-2", tPassword) + label := td.RandString(16) + addressInfo, err := td.vault.NewBLSAccountAddress(label) assert.NoError(t, err) assert.NotEmpty(t, addressInfo.Address) assert.NotEmpty(t, addressInfo.PublicKey) - assert.Equal(t, "m/44'/21888'/3'/1'", addressInfo.Path) + assert.Contains(t, addressInfo.Path, "m/12381'/21888'/2'") + assert.Equal(t, label, addressInfo.Label) - addressInfo, err = td.vault.NewEd25519AccountAddress("addr-3", tPassword) - assert.NoError(t, err) - assert.NotEmpty(t, addressInfo.Address) - assert.NotEmpty(t, addressInfo.PublicKey) - assert.Equal(t, "m/44'/21888'/3'/2'", addressInfo.Path) + pub, _ := bls.PublicKeyFromString(addressInfo.PublicKey) + assert.Equal(t, pub.AccountAddress().String(), addressInfo.Address) } -func TestNewValidatorAddress(t *testing.T) { +func TestNewE225519AccountAddress(t *testing.T) { td := setup(t) - label := td.RandString(16) - addressInfo, err := td.vault.NewValidatorAddress(label) + addressInfo, err := td.vault.NewEd25519AccountAddress("addr-2", tPassword) assert.NoError(t, err) assert.NotEmpty(t, addressInfo.Address) assert.NotEmpty(t, addressInfo.PublicKey) - assert.Contains(t, addressInfo.Path, "m/12381'/21888'/1'") - assert.Equal(t, label, addressInfo.Label) + assert.Equal(t, "m/44'/21888'/3'/1'", addressInfo.Path) + + pub, _ := ed25519.PublicKeyFromString(addressInfo.PublicKey) + assert.Equal(t, pub.AccountAddress().String(), addressInfo.Address) } func TestRecover(t *testing.T) { @@ -278,13 +274,11 @@ func TestRecover(t *testing.T) { assert.NoError(t, err) // Recover addresses - _, err = recovered.NewBLSAccountAddress("addr-1") + _, err = recovered.NewBLSAccountAddress("bls-account-address") assert.NoError(t, err) - _, err = recovered.NewBLSAccountAddress("addr-2") + _, err = recovered.NewEd25519AccountAddress("ed25519-account-address", "") assert.NoError(t, err) - _, err = recovered.NewValidatorAddress("addr-3") - assert.NoError(t, err) - _, err = recovered.NewValidatorAddress("addr-4") + _, err = recovered.NewValidatorAddress("validator-address") assert.NoError(t, err) assert.Equal(t, recovered.Purposes, td.vault.Purposes) @@ -317,8 +311,19 @@ func TestGetPrivateKeys(t *testing.T) { prv, err := td.vault.PrivateKeys(tPassword, []string{info.Address}) assert.NoError(t, err) i := td.vault.AddressInfo(info.Address) - pub, _ := bls.PublicKeyFromString(i.PublicKey) - require.True(t, prv[0].PublicKey().EqualsTo(pub)) + path, _ := addresspath.FromString(info.Path) + + switch path.AddressType() - addresspath.HardenedKeyStart { + case uint32(crypto.AddressTypeBLSAccount), + uint32(crypto.AddressTypeValidator): + pub, _ := bls.PublicKeyFromString(i.PublicKey) + require.True(t, prv[0].PublicKey().EqualsTo(pub)) + case uint32(crypto.AddressTypeEd25519Account): + pub, _ := ed25519.PublicKeyFromString(i.PublicKey) + require.True(t, prv[0].PublicKey().EqualsTo(pub)) + default: + assert.Fail(t, "not supported") + } } }) } @@ -327,19 +332,19 @@ func TestImportPrivateKey(t *testing.T) { td := setup(t) t.Run("Reimporting private key", func(t *testing.T) { - err := td.vault.ImportPrivateKey(tPassword, td.importedPrv.(*bls.PrivateKey)) + err := td.vault.ImportBLSPrivateKey(tPassword, td.importedPrv.(*bls.PrivateKey)) assert.ErrorIs(t, err, ErrAddressExists) }) t.Run("Invalid password", func(t *testing.T) { _, prv := td.RandBLSKeyPair() - err := td.vault.ImportPrivateKey("invalid-password", prv) + err := td.vault.ImportBLSPrivateKey("invalid-password", prv) assert.ErrorIs(t, err, encrypter.ErrInvalidPassword) }) t.Run("Ok", func(t *testing.T) { _, prv := td.RandBLSKeyPair() - assert.NoError(t, td.vault.ImportPrivateKey(tPassword, prv)) + assert.NoError(t, td.vault.ImportBLSPrivateKey(tPassword, prv)) assert.True(t, td.vault.Contains(prv.PublicKeyNative().AccountAddress().String())) assert.True(t, td.vault.Contains(prv.PublicKeyNative().ValidatorAddress().String())) }) @@ -452,7 +457,7 @@ func TestNeuter(t *testing.T) { }) assert.ErrorIs(t, err, ErrNeutered) - err = neutered.ImportPrivateKey("any", td.importedPrv.(*bls.PrivateKey)) + err = neutered.ImportBLSPrivateKey("any", td.importedPrv.(*bls.PrivateKey)) assert.ErrorIs(t, err, ErrNeutered) err = td.vault.Neuter().UpdatePassword("any", "any") diff --git a/wallet/wallet.go b/wallet/wallet.go index ba6e3257f..0f27792be 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -24,13 +24,8 @@ const ( AddressTypeValidator string = "validator" ) -const ( - Version1 = 1 // initial version - Version2 = 2 // supporting Ed25519 = -) - type Wallet struct { - store *store + store *Store path string grpcClient *grpcClient } @@ -59,24 +54,33 @@ func Open(walletPath string, offline bool, options ...Option) (*Wallet, error) { return nil, err } - store := new(store) - err = store.Save(data) + walletStore, err := FromBytes(data) if err != nil { return nil, err } - opts := defaultWalletOpt + err = walletStore.UpgradeWallet(walletPath) + if err != nil { + return nil, err + } + opts := defaultWalletOpt for _, opt := range options { opt(opts) } - return newWallet(walletPath, store, offline, opts) + if err := walletStore.ValidateCRC(); err != nil { + return nil, err + } + + return newWallet(walletPath, walletStore, offline, opts) } // Create creates a wallet from mnemonic (seed phrase) and save it at the // given path. -func Create(walletPath, mnemonic, password string, chain genesis.ChainType, options ...Option) (*Wallet, error) { +func Create(walletPath, mnemonic, password string, chain genesis.ChainType, + options ...Option, +) (*Wallet, error) { opts := defaultWalletOpt for _, opt := range options { @@ -100,7 +104,7 @@ func Create(walletPath, mnemonic, password string, chain genesis.ChainType, opti return nil, ErrInvalidNetwork } - store := &store{ + store := &Store{ Version: Version2, UUID: uuid.New(), CreatedAt: time.Now().Round(time.Second).UTC(), @@ -124,7 +128,7 @@ func Create(walletPath, mnemonic, password string, chain genesis.ChainType, opti return wallet, nil } -func newWallet(walletPath string, store *store, offline bool, option *walletOpt) (*Wallet, error) { +func newWallet(walletPath string, store *Store, offline bool, option *walletOpt) (*Wallet, error) { if !store.Network.IsMainnet() { crypto.AddressHRP = "tpc" crypto.PublicKeyHRP = "tpublic" @@ -385,8 +389,8 @@ func (w *Wallet) AddressFromPath(p string) *vault.AddressInfo { return w.store.Vault.AddressFromPath(p) } -func (w *Wallet) ImportPrivateKey(password string, prv *bls.PrivateKey) error { - return w.store.Vault.ImportPrivateKey(password, prv) +func (w *Wallet) ImportBLSPrivateKey(password string, prv *bls.PrivateKey) error { + return w.store.Vault.ImportBLSPrivateKey(password, prv) } func (w *Wallet) PrivateKey(password, addr string) (crypto.PrivateKey, error) { diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 53ebb25b1..0e6fa8c59 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -97,9 +97,9 @@ func TestOpenWallet(t *testing.T) { assert.NoError(t, util.WriteFile(td.wallet.Path(), []byte("{}"))) _, err := wallet.Open(td.wallet.Path(), true) - assert.ErrorIs(t, err, wallet.CRCNotMatchError{ - Expected: 634125391, - Got: 0, + assert.ErrorIs(t, err, wallet.UnsupportedVersionError{ + WalletVersion: 0, + SupportedVersion: 2, }) }) @@ -164,7 +164,7 @@ func TestImportPrivateKey(t *testing.T) { defer td.Close() _, prv := td.RandBLSKeyPair() - assert.NoError(t, td.wallet.ImportPrivateKey(td.password, prv)) + assert.NoError(t, td.wallet.ImportBLSPrivateKey(td.password, prv)) pub := prv.PublicKeyNative() accAddr := pub.AccountAddress().String() @@ -190,7 +190,7 @@ func TestSignMessage(t *testing.T) { require.NoError(t, err) - err = td.wallet.ImportPrivateKey(td.password, prv) + err = td.wallet.ImportBLSPrivateKey(td.password, prv) assert.NoError(t, err) sig, err := td.wallet.SignMessage(td.password, td.wallet.AllAccountAddresses()[0].Address, msg) From 550d5b5c1e61104c2cb1f1a68bf2682c1160f6af Mon Sep 17 00:00:00 2001 From: b00f Date: Fri, 30 Aug 2024 15:38:14 +0800 Subject: [PATCH 20/25] fix(store): cache Ed25519 Public Keys (#1495) --- cmd/wallet/address.go | 5 +- execution/execution.go | 2 +- execution/execution_test.go | 8 +- sandbox/interface.go | 2 +- sandbox/mock.go | 4 +- sandbox/sandbox.go | 4 +- sandbox/sandbox_test.go | 6 +- state/execution_test.go | 17 ++-- state/state_test.go | 5 +- store/block.go | 29 +++++-- store/interface.go | 5 +- store/mock.go | 7 +- store/store.go | 11 ++- store/store_test.go | 121 ++++++++++++++++----------- store/tx.go | 2 +- sync/handler_blocks_response_test.go | 6 +- types/tx/tx_test.go | 4 +- util/testsuite/testsuite.go | 109 +++++++++++++++++++----- 18 files changed, 229 insertions(+), 118 deletions(-) diff --git a/cmd/wallet/address.go b/cmd/wallet/address.go index 64fc24831..fe5058620 100644 --- a/cmd/wallet/address.go +++ b/cmd/wallet/address.go @@ -87,7 +87,10 @@ func buildNewAddressCmd(parentCmd *cobra.Command) { if *addressType == wallet.AddressTypeBLSAccount { addressInfo, err = wlt.NewBLSAccountAddress(label) } else if *addressType == wallet.AddressTypeEd25519Account { - password := cmd.PromptInput("Password") + password := "" + if wlt.IsEncrypted() { + password = cmd.PromptInput("Password") + } addressInfo, err = wlt.NewEd25519AccountAddress(label, password) } else if *addressType == wallet.AddressTypeValidator { addressInfo, err = wlt.NewValidatorAddress(label) diff --git a/execution/execution.go b/execution/execution.go index 8ec1c326e..9e0955944 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -30,7 +30,7 @@ func CheckAndExecute(trx *tx.Tx, sb sandbox.Sandbox, strict bool) error { } } - if exists := sb.AnyRecentTransaction(trx.ID()); exists { + if exists := sb.RecentTransaction(trx.ID()); exists { return TransactionCommittedError{ ID: trx.ID(), } diff --git a/execution/execution_test.go b/execution/execution_test.go index 6bb8de286..74884f8f2 100644 --- a/execution/execution_test.go +++ b/execution/execution_test.go @@ -16,7 +16,7 @@ func TestTransferLockTime(t *testing.T) { ts := testsuite.NewTestSuite(t) sb := sandbox.MockingSandbox(ts) - rndPubKey, rndPrvKey := ts.RandBLSKeyPair() + rndPubKey, rndPrvKey := ts.RandEd25519KeyPair() rndAccAddr := rndPubKey.AccountAddress() rndAcc := sb.MakeNewAccount(rndAccAddr) rndAcc.AddToBalance(1000 * 1e9) @@ -247,7 +247,7 @@ func TestExecute(t *testing.T) { err := Execute(trx, sb) assert.NoError(t, err) - assert.True(t, sb.AnyRecentTransaction(trx.ID())) + assert.True(t, sb.RecentTransaction(trx.ID())) }) } @@ -296,7 +296,7 @@ func TestCheck(t *testing.T) { err := CheckAndExecute(trx, sb, true) assert.NoError(t, err) - assert.True(t, sb.AnyRecentTransaction(trx.ID())) + assert.True(t, sb.RecentTransaction(trx.ID())) }) } @@ -304,7 +304,7 @@ func TestReplay(t *testing.T) { ts := testsuite.NewTestSuite(t) sb := sandbox.MockingSandbox(ts) - rndPubKey, rndPrvKey := ts.RandBLSKeyPair() + rndPubKey, rndPrvKey := ts.RandEd25519KeyPair() rndAccAddr := rndPubKey.AccountAddress() rndAcc := sb.MakeNewAccount(rndAccAddr) rndAcc.AddToBalance(1e9) diff --git a/sandbox/interface.go b/sandbox/interface.go index a25355335..059ff6f5d 100644 --- a/sandbox/interface.go +++ b/sandbox/interface.go @@ -18,7 +18,7 @@ type Sandbox interface { UpdateAccount(crypto.Address, *account.Account) CommitTransaction(trx *tx.Tx) - AnyRecentTransaction(txID tx.ID) bool + RecentTransaction(txID tx.ID) bool IsBanned(crypto.Address) bool Validator(crypto.Address) *validator.Validator diff --git a/sandbox/mock.go b/sandbox/mock.go index dde44cdc6..ae60daf25 100644 --- a/sandbox/mock.go +++ b/sandbox/mock.go @@ -76,12 +76,12 @@ func (m *MockSandbox) UpdateAccount(addr crypto.Address, acc *account.Account) { m.TestStore.UpdateAccount(addr, acc) } -func (m *MockSandbox) AnyRecentTransaction(txID tx.ID) bool { +func (m *MockSandbox) RecentTransaction(txID tx.ID) bool { if m.TestCommittedTrxs[txID] != nil { return true } - return m.TestStore.AnyRecentTransaction(txID) + return m.TestStore.RecentTransaction(txID) } func (m *MockSandbox) Validator(addr crypto.Address) *validator.Validator { diff --git a/sandbox/sandbox.go b/sandbox/sandbox.go index 87331471e..7bebffce5 100644 --- a/sandbox/sandbox.go +++ b/sandbox/sandbox.go @@ -139,12 +139,12 @@ func (sb *sandbox) UpdateAccount(addr crypto.Address, acc *account.Account) { s.updated = true } -func (sb *sandbox) AnyRecentTransaction(txID tx.ID) bool { +func (sb *sandbox) RecentTransaction(txID tx.ID) bool { if sb.committedTrxs[txID] != nil { return true } - return sb.store.AnyRecentTransaction(txID) + return sb.store.RecentTransaction(txID) } func (sb *sandbox) Validator(addr crypto.Address) *validator.Validator { diff --git a/sandbox/sandbox_test.go b/sandbox/sandbox_test.go index 42f0d84c0..26b36ab8c 100644 --- a/sandbox/sandbox_test.go +++ b/sandbox/sandbox_test.go @@ -136,7 +136,7 @@ func TestAccountChange(t *testing.T) { }) } -func TestAnyRecentTransaction(t *testing.T) { +func TestRecentTransaction(t *testing.T) { td := setup(t) randTx1 := td.GenerateTestTransferTx() @@ -144,8 +144,8 @@ func TestAnyRecentTransaction(t *testing.T) { td.sandbox.CommitTransaction(randTx1) td.sandbox.CommitTransaction(randTx2) - assert.True(t, td.sandbox.AnyRecentTransaction(randTx1.ID())) - assert.True(t, td.sandbox.AnyRecentTransaction(randTx2.ID())) + assert.True(t, td.sandbox.RecentTransaction(randTx1.ID())) + assert.True(t, td.sandbox.RecentTransaction(randTx2.ID())) totalTxFees := randTx1.Fee() + randTx2.Fee() assert.Equal(t, totalTxFees, td.sandbox.AccumulatedFee()) diff --git a/state/execution_test.go b/state/execution_test.go index 8e865b496..5e2a41f53 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -7,6 +7,7 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/tx" + "github.com/pactus-project/pactus/util/testsuite" "github.com/stretchr/testify/assert" ) @@ -20,14 +21,13 @@ func TestProposeBlock(t *testing.T) { invBondTx := td.GenerateTestBondTx() invSortitionTx := td.GenerateTestSortitionTx() - pub, _ := td.RandBLSKeyPair() - validTrx1 := tx.NewTransferTx(lockTime, td.genAccKey.PublicKeyNative().AccountAddress(), - td.RandAccAddress(), 1, 1000) - td.HelperSignTransaction(td.genAccKey, validTrx1) + validTrx1 := td.GenerateTestTransferTx( + testsuite.TransactionWithLockTime(lockTime), + testsuite.TransactionWithEd25519Signer(td.genAccKey)) - validTrx2 := tx.NewBondTx(lockTime, td.genAccKey.PublicKeyNative().AccountAddress(), - pub.ValidatorAddress(), pub, 1000000000, 100000) - td.HelperSignTransaction(td.genAccKey, validTrx2) + validTrx2 := td.GenerateTestTransferTx( + testsuite.TransactionWithLockTime(lockTime), + testsuite.TransactionWithEd25519Signer(td.genAccKey)) assert.NoError(t, td.state.AddPendingTx(invTransferTx)) assert.NoError(t, td.state.AddPendingTx(invBondTx)) @@ -41,9 +41,6 @@ func TestProposeBlock(t *testing.T) { assert.Equal(t, block.Txs{validTrx1, validTrx2}, blk.Transactions()[1:]) assert.True(t, blk.Transactions()[0].IsSubsidyTx()) assert.NoError(t, td.state.CommitBlock(blk, cert)) - - assert.Equal(t, int64(1000000004), td.state.TotalPower()) - assert.Equal(t, int64(4), td.state.committee.TotalPower()) } func TestExecuteBlock(t *testing.T) { diff --git a/state/state_test.go b/state/state_test.go index 2905fa560..593cd1fe2 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -6,6 +6,7 @@ import ( "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/store" @@ -29,7 +30,7 @@ type testData struct { state *state genValKeys []*bls.ValidatorKey - genAccKey *bls.PrivateKey + genAccKey *ed25519.PrivateKey commonTxPool *txpool.MockTxPool } @@ -62,7 +63,7 @@ func setup(t *testing.T) *testData { genAcc1.AddToBalance(21 * 1e15) // 21,000,000.000,000,000 genAcc2 := account.NewAccount(1) genAcc2.AddToBalance(21 * 1e15) // 21,000,000.000,000,000 - genAccPubKey, genAccPrvKey := ts.RandBLSKeyPair() + genAccPubKey, genAccPrvKey := ts.RandEd25519KeyPair() genAccs := map[crypto.Address]*account.Account{ crypto.TreasuryAddress: genAcc1, diff --git a/store/block.go b/store/block.go index 52f22da47..2787a8bbe 100644 --- a/store/block.go +++ b/store/block.go @@ -6,6 +6,7 @@ import ( lru "github.com/hashicorp/golang-lru/v2" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" + "github.com/pactus-project/pactus/crypto/ed25519" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/sortition" "github.com/pactus-project/pactus/types/block" @@ -26,13 +27,13 @@ func blockHashKey(h hash.Hash) []byte { type blockStore struct { db *leveldb.DB - pubKeyCache *lru.Cache[crypto.Address, *bls.PublicKey] + pubKeyCache *lru.Cache[crypto.Address, crypto.PublicKey] seedCache *pairslice.PairSlice[uint32, *sortition.VerifiableSeed] seedCacheWindow uint32 } func newBlockStore(db *leveldb.DB, seedCacheWindow uint32, publicKeyCacheSize int) *blockStore { - pubKeyCache, err := lru.New[crypto.Address, *bls.PublicKey](publicKeyCacheSize) + pubKeyCache, err := lru.New[crypto.Address, crypto.PublicKey](publicKeyCacheSize) if err != nil { return nil } @@ -141,7 +142,7 @@ func (bs *blockStore) hasBlock(height uint32) bool { return tryHas(bs.db, blockKey(height)) } -func (bs *blockStore) publicKey(addr crypto.Address) (*bls.PublicKey, error) { +func (bs *blockStore) publicKey(addr crypto.Address) (crypto.PublicKey, error) { if pubKey, ok := bs.pubKeyCache.Get(addr); ok { return pubKey, nil } @@ -150,9 +151,25 @@ func (bs *blockStore) publicKey(addr crypto.Address) (*bls.PublicKey, error) { if err != nil { return nil, err } - pubKey, err := bls.PublicKeyFromBytes(data) - if err != nil { - return nil, err + var pubKey crypto.PublicKey + switch addr.Type() { + case crypto.AddressTypeValidator, + crypto.AddressTypeBLSAccount: + pubKey, err = bls.PublicKeyFromBytes(data) + if err != nil { + return nil, err + } + case crypto.AddressTypeEd25519Account: + pubKey, err = ed25519.PublicKeyFromBytes(data) + if err != nil { + return nil, err + } + + case crypto.AddressTypeTreasury: + panic("unreachable") + + default: + return nil, PublicKeyNotFoundError{Address: addr} } bs.pubKeyCache.Add(addr, pubKey) diff --git a/store/interface.go b/store/interface.go index 50cd1d9a7..81edcd844 100644 --- a/store/interface.go +++ b/store/interface.go @@ -2,7 +2,6 @@ package store import ( "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/sortition" "github.com/pactus-project/pactus/types/account" @@ -84,8 +83,8 @@ type Reader interface { BlockHash(height uint32) hash.Hash SortitionSeed(blockHeight uint32) *sortition.VerifiableSeed Transaction(id tx.ID) (*CommittedTx, error) - AnyRecentTransaction(id tx.ID) bool - PublicKey(addr crypto.Address) (*bls.PublicKey, error) + RecentTransaction(id tx.ID) bool + PublicKey(addr crypto.Address) (crypto.PublicKey, error) HasAccount(crypto.Address) bool Account(addr crypto.Address) (*account.Account, error) TotalAccounts() int32 diff --git a/store/mock.go b/store/mock.go index f5e773cf6..d9c7045b0 100644 --- a/store/mock.go +++ b/store/mock.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/sortition" "github.com/pactus-project/pactus/types/account" @@ -80,11 +79,11 @@ func (m *MockStore) SortitionSeed(blockHeight uint32) *sortition.VerifiableSeed return nil } -func (m *MockStore) PublicKey(addr crypto.Address) (*bls.PublicKey, error) { +func (m *MockStore) PublicKey(addr crypto.Address) (crypto.PublicKey, error) { for _, blk := range m.Blocks { for _, trx := range blk.Transactions() { if trx.Payload().Signer() == addr { - return trx.PublicKey().(*bls.PublicKey), nil + return trx.PublicKey(), nil } } } @@ -116,7 +115,7 @@ func (m *MockStore) Transaction(id tx.ID) (*CommittedTx, error) { return nil, fmt.Errorf("not found") } -func (m *MockStore) AnyRecentTransaction(id tx.ID) bool { +func (m *MockStore) RecentTransaction(id tx.ID) bool { for _, blk := range m.Blocks { for _, trx := range blk.Transactions() { if trx.ID() == id { diff --git a/store/store.go b/store/store.go index c5e35b91c..f0da3f0b5 100644 --- a/store/store.go +++ b/store/store.go @@ -6,7 +6,6 @@ import ( "sync" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/sortition" "github.com/pactus-project/pactus/types/account" @@ -239,7 +238,7 @@ func (s *store) SortitionSeed(blockHeight uint32) *sortition.VerifiableSeed { return s.blockStore.sortitionSeed(blockHeight) } -func (s *store) PublicKey(addr crypto.Address) (*bls.PublicKey, error) { +func (s *store) PublicKey(addr crypto.Address) (crypto.PublicKey, error) { s.lk.RLock() defer s.lk.RUnlock() @@ -274,11 +273,15 @@ func (s *store) Transaction(id tx.ID) (*CommittedTx, error) { }, nil } -func (s *store) AnyRecentTransaction(id tx.ID) bool { +// RecentTransaction checks if there is a transaction with the given ID +// within the last 8640 blocks. +// The time window for recent transactions is determined by the +// TransactionToLive interval, which is part of the consensus parameters. +func (s *store) RecentTransaction(id tx.ID) bool { s.lk.Lock() defer s.lk.Unlock() - return s.txStore.anyRecentTransaction(id) + return s.txStore.RecentTransaction(id) } func (s *store) HasAccount(addr crypto.Address) bool { diff --git a/store/store_test.go b/store/store_test.go index 9ce7f0220..5c9effacc 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/crypto/hash" "github.com/pactus-project/pactus/types/block" "github.com/pactus-project/pactus/types/tx" @@ -136,14 +135,10 @@ func TestIndexingPublicKeys(t *testing.T) { blk, _ := cBlk.ToBlock() for _, trx := range blk.Transactions() { addr := trx.Payload().Signer() - pubKey, err := td.store.PublicKey(addr) + pub, err := td.store.PublicKey(addr) assert.NoError(t, err) - if addr.IsAccountAddress() { - assert.Equal(t, addr, pubKey.AccountAddress()) - } else if addr.IsValidatorAddress() { - assert.Equal(t, addr, pubKey.ValidatorAddress()) - } + assert.True(t, trx.PublicKey().EqualsTo(pub)) } }) @@ -158,71 +153,82 @@ func TestIndexingPublicKeys(t *testing.T) { func TestStrippedPublicKey(t *testing.T) { td := setup(t, nil) - // Find a public key that we have already indexed in the database. - cBlkOne, _ := td.store.Block(1) - blkOne, _ := cBlkOne.ToBlock() - trx0PubKey := blkOne.Transactions()[0].PublicKey() - assert.NotNil(t, trx0PubKey) - knownPubKey := trx0PubKey.(*bls.PublicKey) - - lastCert := td.store.LastCertificate() - lastHeight := lastCert.Height() - randPubKey, _ := td.RandBLSKeyPair() - - trx0 := tx.NewTransferTx(lastHeight, knownPubKey.AccountAddress(), td.RandAccAddress(), 1, 1) - trx1 := tx.NewTransferTx(lastHeight, randPubKey.AccountAddress(), td.RandAccAddress(), 1, 1) - trx2 := tx.NewTransferTx(lastHeight, randPubKey.AccountAddress(), td.RandAccAddress(), 1, 1) + lastHeight := td.store.LastCertificate().Height() + _, blsPrv := td.RandBLSKeyPair() + committedTrx1 := td.GenerateTestTransferTx( + testsuite.TransactionWithBLSSigner(blsPrv), + ) + _, ed25519Prv := td.RandEd25519KeyPair() + committedTrx2 := td.GenerateTestTransferTx( + testsuite.TransactionWithEd25519Signer(ed25519Prv), + ) + blk0, cert0 := td.GenerateTestBlock(lastHeight+1, + testsuite.BlockWithTransactions([]*tx.Tx{committedTrx1, committedTrx2})) + td.store.SaveBlock(blk0, cert0) + err := td.store.writeBatch() + require.NoError(t, err) - trx0.StripPublicKey() - trx1.SetPublicKey(randPubKey) - trx2.StripPublicKey() + // We have some known and index public key, run tests... + trx1 := td.GenerateTestTransferTx( + testsuite.TransactionWithBLSSigner(blsPrv), + ) + trx2 := td.GenerateTestTransferTx( + testsuite.TransactionWithEd25519Signer(ed25519Prv), + ) + trx3 := td.GenerateTestTransferTx( + testsuite.TransactionWithBLSSigner(blsPrv), + ) + trx4 := td.GenerateTestTransferTx( + testsuite.TransactionWithEd25519Signer(ed25519Prv), + ) + trx5 := td.GenerateTestTransferTx() + + trx3.StripPublicKey() + trx4.StripPublicKey() + trx5.StripPublicKey() tests := []struct { trx *tx.Tx failed bool }{ - {trx0, false}, // indexed public key and stripped - {trx1, false}, // not stripped - {trx2, true}, // unknown public key and stripped + {trx1, false}, // indexed public key and not stripped + {trx2, false}, // indexed public key and not stripped + {trx3, false}, // indexed public key and stripped + {trx4, false}, // indexed public key and stripped + {trx5, true}, // unknown public key and stripped } - for _, test := range tests { + for i, test := range tests { trxs := block.Txs{test.trx} - blk, _ := td.GenerateTestBlock(td.RandHeight(), testsuite.BlockWithTransactions(trxs)) + blockHeight := td.store.LastCertificate().Height() + blk, cert := td.GenerateTestBlock(blockHeight+1, testsuite.BlockWithTransactions(trxs)) + td.store.SaveBlock(blk, cert) + err := td.store.writeBatch() + require.NoError(t, err) - trxData, _ := test.trx.Bytes() - blkData, _ := blk.Bytes() + cBlk, err := td.store.Block(blockHeight + 1) + require.NoError(t, err) - cTrx := CommittedTx{ - store: td.store, - TxID: test.trx.ID(), - Height: lastHeight + 1, - Data: trxData, - } - cBlk := CommittedBlock{ - store: td.store, - BlockHash: blk.Hash(), - Height: lastHeight + 1, - Data: blkData, - } + cTrx, err := td.store.Transaction(test.trx.ID()) + require.NoError(t, err) // if test.failed { _, err := cBlk.ToBlock() assert.ErrorIs(t, err, PublicKeyNotFoundError{ Address: test.trx.Payload().Signer(), - }) + }, "test %d failed, expected error", i+1) _, err = cTrx.ToTx() assert.ErrorIs(t, err, PublicKeyNotFoundError{ Address: test.trx.Payload().Signer(), - }) + }, "test %d failed, expected error", i+1) } else { _, err := cBlk.ToBlock() - assert.NoError(t, err) + assert.NoError(t, err, "test %d failed, not expected error", i+1) _, err = cTrx.ToTx() - assert.NoError(t, err) + assert.NoError(t, err, "test %d failed, not expected error", i+1) } } } @@ -375,3 +381,24 @@ func TestCancelPrune(t *testing.T) { assert.Equal(t, uint32(1), hits) }) } + +func TestRecentTransaction(t *testing.T) { + td := setup(t, nil) + + lastHeight := td.store.LastCertificate().Height() + oldTrx := td.GenerateTestTransferTx() + blkOld, certOld := td.GenerateTestBlock(lastHeight+1, + testsuite.BlockWithTransactions([]*tx.Tx{oldTrx})) + td.store.SaveBlock(blkOld, certOld) + err := td.store.writeBatch() + require.NoError(t, err) + assert.True(t, td.store.RecentTransaction(oldTrx.ID())) + + blk, cert := td.GenerateTestBlock(lastHeight + td.store.txStore.txCacheWindow + 2) + td.store.SaveBlock(blk, cert) + err = td.store.writeBatch() + require.NoError(t, err) + + assert.False(t, td.store.RecentTransaction(oldTrx.ID())) + assert.False(t, td.store.RecentTransaction(td.RandHash())) +} diff --git a/store/tx.go b/store/tx.go index 68292b45c..c2b50e7f9 100644 --- a/store/tx.go +++ b/store/tx.go @@ -61,7 +61,7 @@ func (ts *txStore) pruneCache(currentHeight uint32) { } } -func (ts *txStore) anyRecentTransaction(id tx.ID) bool { +func (ts *txStore) RecentTransaction(id tx.ID) bool { return ts.txCache.Has(id) } diff --git a/sync/handler_blocks_response_test.go b/sync/handler_blocks_response_test.go index 0764dff92..18ab66176 100644 --- a/sync/handler_blocks_response_test.go +++ b/sync/handler_blocks_response_test.go @@ -73,7 +73,7 @@ func TestStrippedPublicKey(t *testing.T) { // Add a new block and keep the signer key _, indexedPrv := td.RandBLSKeyPair() - trx0 := td.GenerateTestTransferTx(testsuite.TransactionWithSigner(indexedPrv)) + trx0 := td.GenerateTestTransferTx(testsuite.TransactionWithBLSSigner(indexedPrv)) trxs0 := []*tx.Tx{trx0} blk0, cert0 := td.GenerateTestBlock(lastHeight+1, testsuite.BlockWithTransactions(trxs0)) err := td.state.CommitBlock(blk0, cert0) @@ -82,12 +82,12 @@ func TestStrippedPublicKey(t *testing.T) { // ----- _, rndPrv := td.RandBLSKeyPair() - trx1 := td.GenerateTestTransferTx(testsuite.TransactionWithSigner(rndPrv)) + trx1 := td.GenerateTestTransferTx(testsuite.TransactionWithBLSSigner(rndPrv)) trx1.StripPublicKey() trxs1 := []*tx.Tx{trx1} blk1, _ := td.GenerateTestBlock(lastHeight+1, testsuite.BlockWithTransactions(trxs1)) - trx2 := td.GenerateTestTransferTx(testsuite.TransactionWithSigner(indexedPrv)) + trx2 := td.GenerateTestTransferTx(testsuite.TransactionWithBLSSigner(indexedPrv)) trx2.StripPublicKey() trxs2 := []*tx.Tx{trx2} blk2, _ := td.GenerateTestBlock(lastHeight+1, testsuite.BlockWithTransactions(trxs2)) diff --git a/types/tx/tx_test.go b/types/tx/tx_test.go index b3893b775..d0d98433b 100644 --- a/types/tx/tx_test.go +++ b/types/tx/tx_test.go @@ -215,7 +215,7 @@ func TestInvalidPayloadType(t *testing.T) { func TestSubsidyTx(t *testing.T) { ts := testsuite.NewTestSuite(t) - pub, prv := ts.RandBLSKeyPair() + pub, prv := ts.RandEd25519KeyPair() t.Run("Has signature", func(t *testing.T) { trx := tx.NewSubsidyTx(ts.RandHeight(), pub.AccountAddress(), 2500) @@ -300,7 +300,7 @@ func TestInvalidSignature(t *testing.T) { t.Run("Invalid sign Bytes", func(t *testing.T) { valKey := ts.RandValKey() - trx0 := ts.GenerateTestUnbondTx(testsuite.TransactionWithSigner(valKey.PrivateKey())) + trx0 := ts.GenerateTestUnbondTx(testsuite.TransactionWithBLSSigner(valKey.PrivateKey())) trx := tx.NewUnbondTx(trx0.LockTime(), valKey.Address(), tx.WithMemo("invalidate signature")) trx.SetPublicKey(trx0.PublicKey()) diff --git a/util/testsuite/testsuite.go b/util/testsuite/testsuite.go index 1b8237161..7adf16dc9 100644 --- a/util/testsuite/testsuite.go +++ b/util/testsuite/testsuite.go @@ -280,8 +280,8 @@ func (ts *TestSuite) RandHash() hash.Hash { // RandAccAddress generates a random account address for testing purposes. func (ts *TestSuite) RandAccAddress() crypto.Address { - isBLSAddress := ts.RandBool() - if isBLSAddress { + useBLSAddress := ts.RandBool() + if useBLSAddress { return crypto.NewAddress(crypto.AddressTypeBLSAccount, ts.RandBytes(20)) } @@ -501,20 +501,32 @@ type TransactionMaker struct { LockTime uint32 Amount amount.Amount Fee amount.Amount - PrvKey *bls.PrivateKey - PubKey *bls.PublicKey + Signer crypto.PrivateKey +} + +func (tm *TransactionMaker) SignerAccountAddress() crypto.Address { + blsPub, ok := tm.Signer.PublicKey().(*bls.PublicKey) + if ok { + return blsPub.AccountAddress() + } + ed25519Pub := tm.Signer.PublicKey().(*ed25519.PublicKey) + + return ed25519Pub.AccountAddress() +} + +func (tm *TransactionMaker) SignerValidatorAddress() crypto.Address { + blsPub := tm.Signer.PublicKey().(*bls.PublicKey) + + return blsPub.ValidatorAddress() } // NewTransactionMaker creates a new TransactionMaker instance with default values. func (ts *TestSuite) NewTransactionMaker() *TransactionMaker { - pub, prv := ts.RandBLSKeyPair() - return &TransactionMaker{ LockTime: ts.RandHeight(), Amount: ts.RandAmount(), Fee: ts.RandFee(), - PrvKey: prv, - PubKey: pub, + Signer: nil, } } @@ -539,11 +551,17 @@ func TransactionWithFee(fee amount.Amount) func(tm *TransactionMaker) { } } -// TransactionWithSigner sets signer to the transaction. -func TransactionWithSigner(signer *bls.PrivateKey) func(tm *TransactionMaker) { +// TransactionWithBLSSigner sets the BLS signer to sign the test transaction. +func TransactionWithBLSSigner(signer *bls.PrivateKey) func(tm *TransactionMaker) { return func(tm *TransactionMaker) { - tm.PrvKey = signer - tm.PubKey = signer.PublicKeyNative() + tm.Signer = signer + } +} + +// TransactionWithEd25519Signer sets the Ed25519 signer to sign the test transaction. +func TransactionWithEd25519Signer(signer *ed25519.PrivateKey) func(tm *TransactionMaker) { + return func(tm *TransactionMaker) { + tm.Signer = signer } } @@ -554,8 +572,21 @@ func (ts *TestSuite) GenerateTestTransferTx(options ...func(tm *TransactionMaker for _, opt := range options { opt(tm) } - trx := tx.NewTransferTx(tm.LockTime, tm.PubKey.AccountAddress(), ts.RandAccAddress(), tm.Amount, tm.Fee) - ts.HelperSignTransaction(tm.PrvKey, trx) + + if tm.Signer == nil { + useBLSSigner := ts.RandBool() + if useBLSSigner { + _, prv := ts.RandBLSKeyPair() + tm.Signer = prv + } else { + _, prv := ts.RandEd25519KeyPair() + tm.Signer = prv + } + } + + sender := tm.SignerAccountAddress() + trx := tx.NewTransferTx(tm.LockTime, sender, ts.RandAccAddress(), tm.Amount, tm.Fee) + ts.HelperSignTransaction(tm.Signer, trx) return trx } @@ -567,8 +598,21 @@ func (ts *TestSuite) GenerateTestBondTx(options ...func(tm *TransactionMaker)) * for _, opt := range options { opt(tm) } - trx := tx.NewBondTx(tm.LockTime, tm.PubKey.AccountAddress(), ts.RandValAddress(), nil, tm.Amount, tm.Fee) - ts.HelperSignTransaction(tm.PrvKey, trx) + + if tm.Signer == nil { + useBLSSigner := ts.RandBool() + if useBLSSigner { + _, prv := ts.RandBLSKeyPair() + tm.Signer = prv + } else { + _, prv := ts.RandEd25519KeyPair() + tm.Signer = prv + } + } + + sender := tm.SignerAccountAddress() + trx := tx.NewBondTx(tm.LockTime, sender, ts.RandValAddress(), nil, tm.Amount, tm.Fee) + ts.HelperSignTransaction(tm.Signer, trx) return trx } @@ -580,9 +624,16 @@ func (ts *TestSuite) GenerateTestSortitionTx(options ...func(tm *TransactionMake for _, opt := range options { opt(tm) } + + if tm.Signer == nil { + _, prv := ts.RandBLSKeyPair() + tm.Signer = prv + } + proof := ts.RandProof() - trx := tx.NewSortitionTx(tm.LockTime, tm.PubKey.ValidatorAddress(), proof) - ts.HelperSignTransaction(tm.PrvKey, trx) + sender := tm.SignerValidatorAddress() + trx := tx.NewSortitionTx(tm.LockTime, sender, proof) + ts.HelperSignTransaction(tm.Signer, trx) return trx } @@ -594,8 +645,15 @@ func (ts *TestSuite) GenerateTestUnbondTx(options ...func(tm *TransactionMaker)) for _, opt := range options { opt(tm) } - trx := tx.NewUnbondTx(tm.LockTime, tm.PubKey.ValidatorAddress()) - ts.HelperSignTransaction(tm.PrvKey, trx) + + if tm.Signer == nil { + _, prv := ts.RandBLSKeyPair() + tm.Signer = prv + } + + sender := tm.SignerValidatorAddress() + trx := tx.NewUnbondTx(tm.LockTime, sender) + ts.HelperSignTransaction(tm.Signer, trx) return trx } @@ -607,8 +665,15 @@ func (ts *TestSuite) GenerateTestWithdrawTx(options ...func(tm *TransactionMaker for _, opt := range options { opt(tm) } - trx := tx.NewWithdrawTx(tm.LockTime, tm.PubKey.ValidatorAddress(), ts.RandAccAddress(), tm.Amount, tm.Fee) - ts.HelperSignTransaction(tm.PrvKey, trx) + + if tm.Signer == nil { + _, prv := ts.RandBLSKeyPair() + tm.Signer = prv + } + + sender := tm.SignerValidatorAddress() + trx := tx.NewWithdrawTx(tm.LockTime, sender, ts.RandAccAddress(), tm.Amount, tm.Fee) + ts.HelperSignTransaction(tm.Signer, trx) return trx } From 57520329ca9fef63ff1d2d1e092f05ec760f9ebc Mon Sep 17 00:00:00 2001 From: Maxi Date: Mon, 2 Sep 2024 14:48:20 +0100 Subject: [PATCH 21/25] feat(grpc): add Ed25519 to AddressType proto (#1492) --- wallet/manager.go | 12 +- www/grpc/gen/dart/blockchain.pb.dart | 34 +- www/grpc/gen/dart/blockchain.pbjson.dart | 8 +- www/grpc/gen/dart/wallet.pb.dart | 14 + www/grpc/gen/dart/wallet.pbenum.dart | 2 + www/grpc/gen/dart/wallet.pbjson.dart | 6 +- www/grpc/gen/docs/grpc.md | 81 +-- www/grpc/gen/docs/json-rpc.md | 99 ++-- www/grpc/gen/go/blockchain.pb.go | 32 +- www/grpc/gen/go/wallet.cobra.pb.go | 1 + www/grpc/gen/go/wallet.pb.go | 316 +++++----- .../blockchain/BlockchainOuterClass.java | 560 +++++++++--------- .../java/pactus/wallet/WalletOuterClass.java | 330 +++++++++-- www/grpc/gen/js/blockchain_pb.js | 100 ++-- www/grpc/gen/js/wallet_pb.js | 35 +- www/grpc/gen/python/blockchain_pb2.py | 2 +- www/grpc/gen/python/blockchain_pb2.pyi | 18 +- www/grpc/gen/python/wallet_pb2.py | 80 +-- www/grpc/gen/python/wallet_pb2.pyi | 8 +- www/grpc/gen/rust/pactus.rs | 16 +- www/grpc/gen/rust/pactus.serde.rs | 52 +- www/grpc/proto/wallet.proto | 5 + www/grpc/swagger-ui/pactus.swagger.json | 25 +- www/grpc/wallet.go | 1 + 24 files changed, 1099 insertions(+), 738 deletions(-) diff --git a/wallet/manager.go b/wallet/manager.go index 50dca6f97..2361d9ff8 100644 --- a/wallet/manager.go +++ b/wallet/manager.go @@ -143,7 +143,7 @@ func (wm *Manager) SignRawTransaction( } func (wm *Manager) GetNewAddress( - walletName, label string, + walletName, label, password string, addressType crypto.AddressType, ) (*vault.AddressInfo, error) { wlt, ok := wm.wallets[walletName] @@ -168,8 +168,16 @@ func (wm *Manager) GetNewAddress( addressInfo = info case crypto.AddressTypeEd25519Account: - return nil, status.Errorf(codes.InvalidArgument, "not supported yet") + if password == "" { + return nil, status.Errorf(codes.InvalidArgument, "password cannot be empty when address type is Ed25519") + } + + info, err := wlt.NewEd25519AccountAddress(label, password) + if err != nil { + return nil, err + } + addressInfo = info case crypto.AddressTypeTreasury: return nil, status.Errorf(codes.InvalidArgument, "invalid address type") diff --git a/www/grpc/gen/dart/blockchain.pb.dart b/www/grpc/gen/dart/blockchain.pb.dart index 8ecf905fb..32465c8d3 100644 --- a/www/grpc/gen/dart/blockchain.pb.dart +++ b/www/grpc/gen/dart/blockchain.pb.dart @@ -1026,23 +1026,23 @@ class GetConsensusInfoRequest extends $pb.GeneratedMessage { class GetConsensusInfoResponse extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetConsensusInfoResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'pactus'), createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'instances', $pb.PbFieldType.PM, subBuilder: ConsensusInfo.create) - ..aOM(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'proposal', subBuilder: Proposal.create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'proposal', subBuilder: Proposal.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'instances', $pb.PbFieldType.PM, subBuilder: ConsensusInfo.create) ..hasRequiredFields = false ; GetConsensusInfoResponse._() : super(); factory GetConsensusInfoResponse({ - $core.Iterable? instances, Proposal? proposal, + $core.Iterable? instances, }) { final _result = create(); - if (instances != null) { - _result.instances.addAll(instances); - } if (proposal != null) { _result.proposal = proposal; } + if (instances != null) { + _result.instances.addAll(instances); + } return _result; } factory GetConsensusInfoResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -1067,18 +1067,18 @@ class GetConsensusInfoResponse extends $pb.GeneratedMessage { static GetConsensusInfoResponse? _defaultInstance; @$pb.TagNumber(1) - $core.List get instances => $_getList(0); + Proposal get proposal => $_getN(0); + @$pb.TagNumber(1) + set proposal(Proposal v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasProposal() => $_has(0); + @$pb.TagNumber(1) + void clearProposal() => clearField(1); + @$pb.TagNumber(1) + Proposal ensureProposal() => $_ensure(0); - @$pb.TagNumber(6) - Proposal get proposal => $_getN(1); - @$pb.TagNumber(6) - set proposal(Proposal v) { setField(6, v); } - @$pb.TagNumber(6) - $core.bool hasProposal() => $_has(1); - @$pb.TagNumber(6) - void clearProposal() => clearField(6); - @$pb.TagNumber(6) - Proposal ensureProposal() => $_ensure(1); + @$pb.TagNumber(2) + $core.List get instances => $_getList(1); } class GetTxPoolContentRequest extends $pb.GeneratedMessage { diff --git a/www/grpc/gen/dart/blockchain.pbjson.dart b/www/grpc/gen/dart/blockchain.pbjson.dart index efffe6152..4203fb851 100644 --- a/www/grpc/gen/dart/blockchain.pbjson.dart +++ b/www/grpc/gen/dart/blockchain.pbjson.dart @@ -226,13 +226,13 @@ final $typed_data.Uint8List getConsensusInfoRequestDescriptor = $convert.base64D const GetConsensusInfoResponse$json = const { '1': 'GetConsensusInfoResponse', '2': const [ - const {'1': 'instances', '3': 1, '4': 3, '5': 11, '6': '.pactus.ConsensusInfo', '10': 'instances'}, - const {'1': 'proposal', '3': 6, '4': 1, '5': 11, '6': '.pactus.Proposal', '10': 'proposal'}, + const {'1': 'proposal', '3': 1, '4': 1, '5': 11, '6': '.pactus.Proposal', '10': 'proposal'}, + const {'1': 'instances', '3': 2, '4': 3, '5': 11, '6': '.pactus.ConsensusInfo', '10': 'instances'}, ], }; /// Descriptor for `GetConsensusInfoResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List getConsensusInfoResponseDescriptor = $convert.base64Decode('ChhHZXRDb25zZW5zdXNJbmZvUmVzcG9uc2USMwoJaW5zdGFuY2VzGAEgAygLMhUucGFjdHVzLkNvbnNlbnN1c0luZm9SCWluc3RhbmNlcxIsCghwcm9wb3NhbBgGIAEoCzIQLnBhY3R1cy5Qcm9wb3NhbFIIcHJvcG9zYWw='); +final $typed_data.Uint8List getConsensusInfoResponseDescriptor = $convert.base64Decode('ChhHZXRDb25zZW5zdXNJbmZvUmVzcG9uc2USLAoIcHJvcG9zYWwYASABKAsyEC5wYWN0dXMuUHJvcG9zYWxSCHByb3Bvc2FsEjMKCWluc3RhbmNlcxgCIAMoCzIVLnBhY3R1cy5Db25zZW5zdXNJbmZvUglpbnN0YW5jZXM='); @$core.Deprecated('Use getTxPoolContentRequestDescriptor instead') const GetTxPoolContentRequest$json = const { '1': 'GetTxPoolContentRequest', @@ -394,9 +394,9 @@ const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> Blockchain '.pactus.ValidatorInfo': ValidatorInfo$json, '.pactus.GetConsensusInfoRequest': GetConsensusInfoRequest$json, '.pactus.GetConsensusInfoResponse': GetConsensusInfoResponse$json, + '.pactus.Proposal': Proposal$json, '.pactus.ConsensusInfo': ConsensusInfo$json, '.pactus.VoteInfo': VoteInfo$json, - '.pactus.Proposal': Proposal$json, '.pactus.GetAccountRequest': GetAccountRequest$json, '.pactus.GetAccountResponse': GetAccountResponse$json, '.pactus.AccountInfo': AccountInfo$json, diff --git a/www/grpc/gen/dart/wallet.pb.dart b/www/grpc/gen/dart/wallet.pb.dart index 38dc533d8..779f3ee1c 100644 --- a/www/grpc/gen/dart/wallet.pb.dart +++ b/www/grpc/gen/dart/wallet.pb.dart @@ -314,6 +314,7 @@ class GetNewAddressRequest extends $pb.GeneratedMessage { ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'walletName') ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'addressType', $pb.PbFieldType.OE, defaultOrMaker: AddressType.ADDRESS_TYPE_TREASURY, valueOf: AddressType.valueOf, enumValues: AddressType.values) ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'label') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'password') ..hasRequiredFields = false ; @@ -322,6 +323,7 @@ class GetNewAddressRequest extends $pb.GeneratedMessage { $core.String? walletName, AddressType? addressType, $core.String? label, + $core.String? password, }) { final _result = create(); if (walletName != null) { @@ -333,6 +335,9 @@ class GetNewAddressRequest extends $pb.GeneratedMessage { if (label != null) { _result.label = label; } + if (password != null) { + _result.password = password; + } return _result; } factory GetNewAddressRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -382,6 +387,15 @@ class GetNewAddressRequest extends $pb.GeneratedMessage { $core.bool hasLabel() => $_has(2); @$pb.TagNumber(3) void clearLabel() => clearField(3); + + @$pb.TagNumber(4) + $core.String get password => $_getSZ(3); + @$pb.TagNumber(4) + set password($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasPassword() => $_has(3); + @$pb.TagNumber(4) + void clearPassword() => clearField(4); } class GetNewAddressResponse extends $pb.GeneratedMessage { diff --git a/www/grpc/gen/dart/wallet.pbenum.dart b/www/grpc/gen/dart/wallet.pbenum.dart index 85cbcaf4a..bc78ae45d 100644 --- a/www/grpc/gen/dart/wallet.pbenum.dart +++ b/www/grpc/gen/dart/wallet.pbenum.dart @@ -13,11 +13,13 @@ class AddressType extends $pb.ProtobufEnum { static const AddressType ADDRESS_TYPE_TREASURY = AddressType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ADDRESS_TYPE_TREASURY'); static const AddressType ADDRESS_TYPE_VALIDATOR = AddressType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ADDRESS_TYPE_VALIDATOR'); static const AddressType ADDRESS_TYPE_BLS_ACCOUNT = AddressType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ADDRESS_TYPE_BLS_ACCOUNT'); + static const AddressType ADDRESS_TYPE_ED25519_ACCOUNT = AddressType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ADDRESS_TYPE_ED25519_ACCOUNT'); static const $core.List values = [ ADDRESS_TYPE_TREASURY, ADDRESS_TYPE_VALIDATOR, ADDRESS_TYPE_BLS_ACCOUNT, + ADDRESS_TYPE_ED25519_ACCOUNT, ]; static final $core.Map<$core.int, AddressType> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/www/grpc/gen/dart/wallet.pbjson.dart b/www/grpc/gen/dart/wallet.pbjson.dart index 25e84a7fc..64d87bbeb 100644 --- a/www/grpc/gen/dart/wallet.pbjson.dart +++ b/www/grpc/gen/dart/wallet.pbjson.dart @@ -15,11 +15,12 @@ const AddressType$json = const { const {'1': 'ADDRESS_TYPE_TREASURY', '2': 0}, const {'1': 'ADDRESS_TYPE_VALIDATOR', '2': 1}, const {'1': 'ADDRESS_TYPE_BLS_ACCOUNT', '2': 2}, + const {'1': 'ADDRESS_TYPE_ED25519_ACCOUNT', '2': 3}, ], }; /// Descriptor for `AddressType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List addressTypeDescriptor = $convert.base64Decode('CgtBZGRyZXNzVHlwZRIZChVBRERSRVNTX1RZUEVfVFJFQVNVUlkQABIaChZBRERSRVNTX1RZUEVfVkFMSURBVE9SEAESHAoYQUREUkVTU19UWVBFX0JMU19BQ0NPVU5UEAI='); +final $typed_data.Uint8List addressTypeDescriptor = $convert.base64Decode('CgtBZGRyZXNzVHlwZRIZChVBRERSRVNTX1RZUEVfVFJFQVNVUlkQABIaChZBRERSRVNTX1RZUEVfVkFMSURBVE9SEAESHAoYQUREUkVTU19UWVBFX0JMU19BQ0NPVU5UEAISIAocQUREUkVTU19UWVBFX0VEMjU1MTlfQUNDT1VOVBAD'); @$core.Deprecated('Use addressInfoDescriptor instead') const AddressInfo$json = const { '1': 'AddressInfo', @@ -75,11 +76,12 @@ const GetNewAddressRequest$json = const { const {'1': 'wallet_name', '3': 1, '4': 1, '5': 9, '10': 'walletName'}, const {'1': 'address_type', '3': 2, '4': 1, '5': 14, '6': '.pactus.AddressType', '10': 'addressType'}, const {'1': 'label', '3': 3, '4': 1, '5': 9, '10': 'label'}, + const {'1': 'password', '3': 4, '4': 1, '5': 9, '10': 'password'}, ], }; /// Descriptor for `GetNewAddressRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List getNewAddressRequestDescriptor = $convert.base64Decode('ChRHZXROZXdBZGRyZXNzUmVxdWVzdBIfCgt3YWxsZXRfbmFtZRgBIAEoCVIKd2FsbGV0TmFtZRI2CgxhZGRyZXNzX3R5cGUYAiABKA4yEy5wYWN0dXMuQWRkcmVzc1R5cGVSC2FkZHJlc3NUeXBlEhQKBWxhYmVsGAMgASgJUgVsYWJlbA=='); +final $typed_data.Uint8List getNewAddressRequestDescriptor = $convert.base64Decode('ChRHZXROZXdBZGRyZXNzUmVxdWVzdBIfCgt3YWxsZXRfbmFtZRgBIAEoCVIKd2FsbGV0TmFtZRI2CgxhZGRyZXNzX3R5cGUYAiABKA4yEy5wYWN0dXMuQWRkcmVzc1R5cGVSC2FkZHJlc3NUeXBlEhQKBWxhYmVsGAMgASgJUgVsYWJlbBIaCghwYXNzd29yZBgEIAEoCVIIcGFzc3dvcmQ='); @$core.Deprecated('Use getNewAddressResponseDescriptor instead') const GetNewAddressResponse$json = const { '1': 'GetNewAddressResponse', diff --git a/www/grpc/gen/docs/grpc.md b/www/grpc/gen/docs/grpc.md index f7c5ca49f..b0c4bc67a 100644 --- a/www/grpc/gen/docs/grpc.md +++ b/www/grpc/gen/docs/grpc.md @@ -1423,6 +1423,41 @@ Message has no fields. + proposal + Proposal + + The proposal of the consensus info. + + + + proposal.height + uint32 + + The height of the proposal. + + + + proposal.round + int32 + + The round of the proposal. + + + + proposal.block_data + string + + The block data of the proposal. + + + + proposal.signature_data + string + + The signature data of the proposal. + + + instances repeated ConsensusInfo @@ -1513,42 +1548,7 @@ committee. The change-proposer value of the vote. - - proposal - Proposal - - The proposal of the consensus info. - - - - proposal.height - uint32 - - The height of the proposal. - - - - proposal.round - int32 - - The round of the proposal. - - - - proposal.block_data - string - - The block data of the proposal. - - - - proposal.signature_data - string - - The signature data of the proposal. - - - + ### GetAccount @@ -2924,6 +2924,8 @@ public key.

      Should not be used to generate new addresses.)
    • ADDRESS_TYPE_VALIDATOR = 1 (Validator address type.)
    • ADDRESS_TYPE_BLS_ACCOUNT = 2 (Account address type with BLS signature scheme.)
    • +
    • ADDRESS_TYPE_ED25519_ACCOUNT = 3 (Account address type with Ed25519 signature scheme. +Note: Generating a new Ed25519 address requires the wallet password.)
    @@ -2934,6 +2936,13 @@ Should not be used to generate new addresses.) A label for the new address. + + password + string + + Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT. + +

    GetNewAddressResponse Response

    diff --git a/www/grpc/gen/docs/json-rpc.md b/www/grpc/gen/docs/json-rpc.md index a28e42013..ee6ec9275 100644 --- a/www/grpc/gen/docs/json-rpc.md +++ b/www/grpc/gen/docs/json-rpc.md @@ -243,7 +243,7 @@ parameters.

    verbosity - numeric + string (Enum) The verbosity level for transaction details.
    Available values:
      @@ -326,7 +326,7 @@ parameters.

      transaction.payload_type - numeric + string (Enum) The type of transaction payload.
      Available values:
        @@ -503,7 +503,7 @@ and payload type.

        payload_type - numeric + string (Enum) The type of transaction payload.
        Available values:
          @@ -889,7 +889,7 @@ parameters.

          verbosity - numeric + string (Enum) The verbosity level for block information.
          Available values:
            @@ -1072,7 +1072,7 @@ BLOCK_TRANSACTIONS. txs[].payload_type - numeric + string (Enum) The type of transaction payload.
            Available values:
              @@ -1474,6 +1474,41 @@ Parameters has no fields. + proposal + object + + The proposal of the consensus info. + + + + proposal.height + numeric + + The height of the proposal. + + + + proposal.round + numeric + + The round of the proposal. + + + + proposal.block_data + string + + The block data of the proposal. + + + + proposal.signature_data + string + + The signature data of the proposal. + + + instances repeated object @@ -1518,7 +1553,7 @@ committee. instances[].votes[].type - numeric + string (Enum) The type of the vote.
              Available values:
                @@ -1564,42 +1599,7 @@ committee. The change-proposer value of the vote. - - proposal - object - - The proposal of the consensus info. - - - - proposal.height - numeric - - The height of the proposal. - - - - proposal.round - numeric - - The round of the proposal. - - - - proposal.block_data - string - - The block data of the proposal. - - - - proposal.signature_data - string - - The signature data of the proposal. - - - + ### pactus.blockchain.get_account @@ -1966,7 +1966,7 @@ address.

                payload_type - numeric + string (Enum) The type of transactions to retrieve from the transaction pool. 0 means all types. @@ -2040,7 +2040,7 @@ types. txs[].payload_type - numeric + string (Enum) The type of transaction payload.
                Available values:
                  @@ -2967,7 +2967,7 @@ public key.

                  address_type - numeric + string (Enum) The type of address to generate.
                  Available values:
                    @@ -2975,6 +2975,8 @@ public key.

                    Should not be used to generate new addresses.)
                  • ADDRESS_TYPE_VALIDATOR = 1 (Validator address type.)
                  • ADDRESS_TYPE_BLS_ACCOUNT = 2 (Account address type with BLS signature scheme.)
                  • +
                  • ADDRESS_TYPE_ED25519_ACCOUNT = 3 (Account address type with Ed25519 signature scheme. +Note: Generating a new Ed25519 address requires the wallet password.)
                  @@ -2985,6 +2987,13 @@ Should not be used to generate new addresses.) A label for the new address. + + password + string + + Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT. + +

                  Result

                  diff --git a/www/grpc/gen/go/blockchain.pb.go b/www/grpc/gen/go/blockchain.pb.go index 57b401540..70d8f6336 100644 --- a/www/grpc/gen/go/blockchain.pb.go +++ b/www/grpc/gen/go/blockchain.pb.go @@ -1133,10 +1133,10 @@ type GetConsensusInfoResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // List of consensus instances. - Instances []*ConsensusInfo `protobuf:"bytes,1,rep,name=instances,proto3" json:"instances,omitempty"` // The proposal of the consensus info. - Proposal *Proposal `protobuf:"bytes,6,opt,name=proposal,proto3" json:"proposal,omitempty"` + Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` + // List of consensus instances. + Instances []*ConsensusInfo `protobuf:"bytes,2,rep,name=instances,proto3" json:"instances,omitempty"` } func (x *GetConsensusInfoResponse) Reset() { @@ -1171,16 +1171,16 @@ func (*GetConsensusInfoResponse) Descriptor() ([]byte, []int) { return file_blockchain_proto_rawDescGZIP(), []int{18} } -func (x *GetConsensusInfoResponse) GetInstances() []*ConsensusInfo { +func (x *GetConsensusInfoResponse) GetProposal() *Proposal { if x != nil { - return x.Instances + return x.Proposal } return nil } -func (x *GetConsensusInfoResponse) GetProposal() *Proposal { +func (x *GetConsensusInfoResponse) GetInstances() []*ConsensusInfo { if x != nil { - return x.Proposal + return x.Instances } return nil } @@ -2029,13 +2029,13 @@ var file_blockchain_proto_rawDesc = []byte{ 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7d, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, - 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x08, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, - 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0x51, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x61, 0x6c, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, + 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x63, 0x74, @@ -2257,8 +2257,8 @@ var file_blockchain_proto_depIdxs = []int32{ 26, // 4: pactus.GetBlockResponse.prev_cert:type_name -> pactus.CertificateInfo 30, // 5: pactus.GetBlockResponse.txs:type_name -> pactus.TransactionInfo 23, // 6: pactus.GetBlockchainInfoResponse.committee_validators:type_name -> pactus.ValidatorInfo - 28, // 7: pactus.GetConsensusInfoResponse.instances:type_name -> pactus.ConsensusInfo - 29, // 8: pactus.GetConsensusInfoResponse.proposal:type_name -> pactus.Proposal + 29, // 7: pactus.GetConsensusInfoResponse.proposal:type_name -> pactus.Proposal + 28, // 8: pactus.GetConsensusInfoResponse.instances:type_name -> pactus.ConsensusInfo 31, // 9: pactus.GetTxPoolContentRequest.payload_type:type_name -> pactus.PayloadType 30, // 10: pactus.GetTxPoolContentResponse.txs:type_name -> pactus.TransactionInfo 1, // 11: pactus.VoteInfo.type:type_name -> pactus.VoteType diff --git a/www/grpc/gen/go/wallet.cobra.pb.go b/www/grpc/gen/go/wallet.cobra.pb.go index c9b14d949..82df0534d 100644 --- a/www/grpc/gen/go/wallet.cobra.pb.go +++ b/www/grpc/gen/go/wallet.cobra.pb.go @@ -373,6 +373,7 @@ func _WalletGetNewAddressCommand(cfg *client.Config) *cobra.Command { cmd.PersistentFlags().StringVar(&req.WalletName, cfg.FlagNamer("WalletName"), "", "The name of the wallet to generate a new address.") flag.EnumVar(cmd.PersistentFlags(), &req.AddressType, cfg.FlagNamer("AddressType"), "The type of address to generate.") cmd.PersistentFlags().StringVar(&req.Label, cfg.FlagNamer("Label"), "", "A label for the new address.") + cmd.PersistentFlags().StringVar(&req.Password, cfg.FlagNamer("Password"), "", "Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.") return cmd } diff --git a/www/grpc/gen/go/wallet.pb.go b/www/grpc/gen/go/wallet.pb.go index 61a05eba7..b57a7a9c6 100644 --- a/www/grpc/gen/go/wallet.pb.go +++ b/www/grpc/gen/go/wallet.pb.go @@ -33,6 +33,9 @@ const ( AddressType_ADDRESS_TYPE_VALIDATOR AddressType = 1 // Account address type with BLS signature scheme. AddressType_ADDRESS_TYPE_BLS_ACCOUNT AddressType = 2 + // Account address type with Ed25519 signature scheme. + // Note: Generating a new Ed25519 address requires the wallet password. + AddressType_ADDRESS_TYPE_ED25519_ACCOUNT AddressType = 3 ) // Enum value maps for AddressType. @@ -41,11 +44,13 @@ var ( 0: "ADDRESS_TYPE_TREASURY", 1: "ADDRESS_TYPE_VALIDATOR", 2: "ADDRESS_TYPE_BLS_ACCOUNT", + 3: "ADDRESS_TYPE_ED25519_ACCOUNT", } AddressType_value = map[string]int32{ - "ADDRESS_TYPE_TREASURY": 0, - "ADDRESS_TYPE_VALIDATOR": 1, - "ADDRESS_TYPE_BLS_ACCOUNT": 2, + "ADDRESS_TYPE_TREASURY": 0, + "ADDRESS_TYPE_VALIDATOR": 1, + "ADDRESS_TYPE_BLS_ACCOUNT": 2, + "ADDRESS_TYPE_ED25519_ACCOUNT": 3, } ) @@ -356,6 +361,8 @@ type GetNewAddressRequest struct { AddressType AddressType `protobuf:"varint,2,opt,name=address_type,json=addressType,proto3,enum=pactus.AddressType" json:"address_type,omitempty"` // A label for the new address. Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label,omitempty"` + // Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT. + Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"` } func (x *GetNewAddressRequest) Reset() { @@ -411,6 +418,13 @@ func (x *GetNewAddressRequest) GetLabel() string { return "" } +func (x *GetNewAddressRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + // Response message containing the newly generated address. type GetNewAddressResponse struct { state protoimpl.MessageState @@ -1379,7 +1393,7 @@ var file_wallet_proto_rawDesc = []byte{ 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x22, - 0x85, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0xa1, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0c, 0x61, 0x64, 0x64, @@ -1387,154 +1401,158 @@ var file_wallet_proto_rawDesc = []byte{ 0x13, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x70, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4e, 0x65, - 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x36, 0x0a, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, - 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x6f, 0x0a, 0x14, 0x52, 0x65, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x38, 0x0a, 0x15, 0x52, 0x65, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x52, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x32, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x22, 0x34, 0x0a, 0x11, - 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x22, 0x70, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, + 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x6f, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x38, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x22, 0x52, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x22, 0x32, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x6d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x22, 0x34, 0x0a, 0x11, 0x4c, 0x6f, 0x61, 0x64, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x35, + 0x0a, 0x12, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x57, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x37, 0x0a, + 0x14, 0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x4b, 0x65, 0x79, 0x22, 0x37, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x81, 0x01, 0x0a, + 0x19, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x72, + 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x22, 0x79, 0x0a, 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, + 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, + 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x61, 0x77, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x39, 0x0a, 0x16, 0x47, + 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5f, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, + 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0x35, 0x0a, 0x12, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x55, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x22, 0x37, 0x0a, 0x14, 0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x1a, 0x47, 0x65, - 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x37, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x81, 0x01, 0x0a, 0x19, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, + 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x27, 0x0a, 0x0f, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x61, 0x77, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x22, 0x79, 0x0a, 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x39, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5f, 0x0a, 0x17, 0x47, 0x65, - 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x12, - 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, - 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x22, 0x33, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x62, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x44, 0x44, 0x52, 0x45, - 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x41, 0x53, 0x55, 0x52, 0x59, - 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1c, - 0x0a, 0x18, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, - 0x4c, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x02, 0x32, 0xb2, 0x06, 0x0a, - 0x06, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x49, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x65, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x43, 0x0a, 0x0a, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x19, - 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x61, 0x63, 0x74, - 0x75, 0x73, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x57, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x55, - 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x55, 0x6e, 0x6c, 0x6f, - 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x70, 0x61, 0x63, - 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, - 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x5e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, - 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, - 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, - 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x58, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, - 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x53, 0x69, 0x67, - 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, - 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x41, 0x0a, 0x0d, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x61, 0x63, 0x74, 0x75, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x61, - 0x63, 0x74, 0x75, 0x73, 0x2f, 0x77, 0x77, 0x77, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x61, - 0x63, 0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x33, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x2a, 0x84, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x41, 0x53, 0x55, 0x52, 0x59, 0x10, 0x00, 0x12, + 0x1a, 0x0a, 0x16, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x41, + 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4c, 0x53, 0x5f, + 0x41, 0x43, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x44, 0x44, + 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, + 0x39, 0x5f, 0x41, 0x43, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x03, 0x32, 0xb2, 0x06, 0x0a, 0x06, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x49, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x43, 0x0a, 0x0a, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x19, 0x2e, + 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, + 0x73, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x57, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x55, 0x6e, + 0x6c, 0x6f, 0x61, 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x55, 0x6e, 0x6c, 0x6f, 0x61, + 0x64, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x54, + 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x54, + 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x70, 0x61, 0x63, 0x74, + 0x75, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, + 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x5e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x61, + 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x1c, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, + 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, + 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x20, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x41, 0x0a, 0x0d, 0x70, 0x61, 0x63, 0x74, 0x75, 0x73, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, + 0x63, 0x74, 0x75, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x61, 0x63, + 0x74, 0x75, 0x73, 0x2f, 0x77, 0x77, 0x77, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x61, 0x63, + 0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java b/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java index 3241713b1..696ee802c 100644 --- a/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java +++ b/www/grpc/gen/java/pactus/blockchain/BlockchainOuterClass.java @@ -13053,74 +13053,74 @@ public interface GetConsensusInfoResponseOrBuilder extends /** *
                  -     * List of consensus instances.
                  +     * The proposal of the consensus info.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return Whether the proposal field is set. */ - java.util.List - getInstancesList(); + boolean hasProposal(); /** *
                  -     * List of consensus instances.
                  +     * The proposal of the consensus info.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return The proposal. */ - pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int index); + pactus.blockchain.BlockchainOuterClass.Proposal getProposal(); /** *
                  -     * List of consensus instances.
                  +     * The proposal of the consensus info.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; */ - int getInstancesCount(); + pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder(); + /** *
                        * List of consensus instances.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ - java.util.List - getInstancesOrBuilderList(); + java.util.List + getInstancesList(); /** *
                        * List of consensus instances.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ - pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( - int index); - + pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int index); /** *
                  -     * The proposal of the consensus info.
                  +     * List of consensus instances.
                        * 
                  * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - * @return Whether the proposal field is set. + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ - boolean hasProposal(); + int getInstancesCount(); /** *
                  -     * The proposal of the consensus info.
                  +     * List of consensus instances.
                        * 
                  * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - * @return The proposal. + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ - pactus.blockchain.BlockchainOuterClass.Proposal getProposal(); + java.util.List + getInstancesOrBuilderList(); /** *
                  -     * The proposal of the consensus info.
                  +     * List of consensus instances.
                        * 
                  * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ - pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder(); + pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( + int index); } /** *
                  @@ -13167,102 +13167,102 @@ protected java.lang.Object newInstance(
                                 pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse.class, pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse.Builder.class);
                       }
                   
                  -    public static final int INSTANCES_FIELD_NUMBER = 1;
                  -    private java.util.List instances_;
                  +    public static final int PROPOSAL_FIELD_NUMBER = 1;
                  +    private pactus.blockchain.BlockchainOuterClass.Proposal proposal_;
                       /**
                        * 
                  -     * List of consensus instances.
                  +     * The proposal of the consensus info.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return Whether the proposal field is set. */ @java.lang.Override - public java.util.List getInstancesList() { - return instances_; + public boolean hasProposal() { + return proposal_ != null; } /** *
                  -     * List of consensus instances.
                  +     * The proposal of the consensus info.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return The proposal. */ @java.lang.Override - public java.util.List - getInstancesOrBuilderList() { - return instances_; + public pactus.blockchain.BlockchainOuterClass.Proposal getProposal() { + return proposal_ == null ? pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; } /** *
                  -     * List of consensus instances.
                  +     * The proposal of the consensus info.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; */ @java.lang.Override - public int getInstancesCount() { - return instances_.size(); + public pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder() { + return getProposal(); } + + public static final int INSTANCES_FIELD_NUMBER = 2; + private java.util.List instances_; /** *
                        * List of consensus instances.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ @java.lang.Override - public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int index) { - return instances_.get(index); + public java.util.List getInstancesList() { + return instances_; } /** *
                        * List of consensus instances.
                        * 
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ @java.lang.Override - public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( - int index) { - return instances_.get(index); + public java.util.List + getInstancesOrBuilderList() { + return instances_; } - - public static final int PROPOSAL_FIELD_NUMBER = 6; - private pactus.blockchain.BlockchainOuterClass.Proposal proposal_; /** *
                  -     * The proposal of the consensus info.
                  +     * List of consensus instances.
                        * 
                  * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - * @return Whether the proposal field is set. + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ @java.lang.Override - public boolean hasProposal() { - return proposal_ != null; + public int getInstancesCount() { + return instances_.size(); } /** *
                  -     * The proposal of the consensus info.
                  +     * List of consensus instances.
                        * 
                  * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - * @return The proposal. + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ @java.lang.Override - public pactus.blockchain.BlockchainOuterClass.Proposal getProposal() { - return proposal_ == null ? pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; + public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int index) { + return instances_.get(index); } /** *
                  -     * The proposal of the consensus info.
                  +     * List of consensus instances.
                        * 
                  * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ @java.lang.Override - public pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder() { - return getProposal(); + public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( + int index) { + return instances_.get(index); } private byte memoizedIsInitialized = -1; @@ -13279,11 +13279,11 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - for (int i = 0; i < instances_.size(); i++) { - output.writeMessage(1, instances_.get(i)); - } if (proposal_ != null) { - output.writeMessage(6, getProposal()); + output.writeMessage(1, getProposal()); + } + for (int i = 0; i < instances_.size(); i++) { + output.writeMessage(2, instances_.get(i)); } getUnknownFields().writeTo(output); } @@ -13294,13 +13294,13 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - for (int i = 0; i < instances_.size(); i++) { + if (proposal_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, instances_.get(i)); + .computeMessageSize(1, getProposal()); } - if (proposal_ != null) { + for (int i = 0; i < instances_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getProposal()); + .computeMessageSize(2, instances_.get(i)); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -13317,13 +13317,13 @@ public boolean equals(final java.lang.Object obj) { } pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse other = (pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse) obj; - if (!getInstancesList() - .equals(other.getInstancesList())) return false; if (hasProposal() != other.hasProposal()) return false; if (hasProposal()) { if (!getProposal() .equals(other.getProposal())) return false; } + if (!getInstancesList() + .equals(other.getInstancesList())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -13335,14 +13335,14 @@ public int hashCode() { } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); - if (getInstancesCount() > 0) { - hash = (37 * hash) + INSTANCES_FIELD_NUMBER; - hash = (53 * hash) + getInstancesList().hashCode(); - } if (hasProposal()) { hash = (37 * hash) + PROPOSAL_FIELD_NUMBER; hash = (53 * hash) + getProposal().hashCode(); } + if (getInstancesCount() > 0) { + hash = (37 * hash) + INSTANCES_FIELD_NUMBER; + hash = (53 * hash) + getInstancesList().hashCode(); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -13475,6 +13475,12 @@ private Builder( @java.lang.Override public Builder clear() { super.clear(); + if (proposalBuilder_ == null) { + proposal_ = null; + } else { + proposal_ = null; + proposalBuilder_ = null; + } if (instancesBuilder_ == null) { instances_ = java.util.Collections.emptyList(); } else { @@ -13482,12 +13488,6 @@ public Builder clear() { instancesBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000001); - if (proposalBuilder_ == null) { - proposal_ = null; - } else { - proposal_ = null; - proposalBuilder_ = null; - } return this; } @@ -13515,6 +13515,11 @@ public pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse build() { public pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse buildPartial() { pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse result = new pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse(this); int from_bitField0_ = bitField0_; + if (proposalBuilder_ == null) { + result.proposal_ = proposal_; + } else { + result.proposal_ = proposalBuilder_.build(); + } if (instancesBuilder_ == null) { if (((bitField0_ & 0x00000001) != 0)) { instances_ = java.util.Collections.unmodifiableList(instances_); @@ -13524,11 +13529,6 @@ public pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse buildPart } else { result.instances_ = instancesBuilder_.build(); } - if (proposalBuilder_ == null) { - result.proposal_ = proposal_; - } else { - result.proposal_ = proposalBuilder_.build(); - } onBuilt(); return result; } @@ -13577,6 +13577,9 @@ public Builder mergeFrom(com.google.protobuf.Message other) { public Builder mergeFrom(pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse other) { if (other == pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse.getDefaultInstance()) return this; + if (other.hasProposal()) { + mergeProposal(other.getProposal()); + } if (instancesBuilder_ == null) { if (!other.instances_.isEmpty()) { if (instances_.isEmpty()) { @@ -13603,9 +13606,6 @@ public Builder mergeFrom(pactus.blockchain.BlockchainOuterClass.GetConsensusInfo } } } - if (other.hasProposal()) { - mergeProposal(other.getProposal()); - } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -13633,6 +13633,13 @@ public Builder mergeFrom( done = true; break; case 10: { + input.readMessage( + getProposalFieldBuilder().getBuilder(), + extensionRegistry); + + break; + } // case 10 + case 18: { pactus.blockchain.BlockchainOuterClass.ConsensusInfo m = input.readMessage( pactus.blockchain.BlockchainOuterClass.ConsensusInfo.parser(), @@ -13644,14 +13651,7 @@ public Builder mergeFrom( instancesBuilder_.addMessage(m); } break; - } // case 10 - case 50: { - input.readMessage( - getProposalFieldBuilder().getBuilder(), - extensionRegistry); - - break; - } // case 50 + } // case 18 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -13669,6 +13669,161 @@ public Builder mergeFrom( } private int bitField0_; + private pactus.blockchain.BlockchainOuterClass.Proposal proposal_; + private com.google.protobuf.SingleFieldBuilderV3< + pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder> proposalBuilder_; + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return Whether the proposal field is set. + */ + public boolean hasProposal() { + return proposalBuilder_ != null || proposal_ != null; + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return The proposal. + */ + public pactus.blockchain.BlockchainOuterClass.Proposal getProposal() { + if (proposalBuilder_ == null) { + return proposal_ == null ? pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; + } else { + return proposalBuilder_.getMessage(); + } + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + public Builder setProposal(pactus.blockchain.BlockchainOuterClass.Proposal value) { + if (proposalBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + proposal_ = value; + onChanged(); + } else { + proposalBuilder_.setMessage(value); + } + + return this; + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + public Builder setProposal( + pactus.blockchain.BlockchainOuterClass.Proposal.Builder builderForValue) { + if (proposalBuilder_ == null) { + proposal_ = builderForValue.build(); + onChanged(); + } else { + proposalBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + public Builder mergeProposal(pactus.blockchain.BlockchainOuterClass.Proposal value) { + if (proposalBuilder_ == null) { + if (proposal_ != null) { + proposal_ = + pactus.blockchain.BlockchainOuterClass.Proposal.newBuilder(proposal_).mergeFrom(value).buildPartial(); + } else { + proposal_ = value; + } + onChanged(); + } else { + proposalBuilder_.mergeFrom(value); + } + + return this; + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + public Builder clearProposal() { + if (proposalBuilder_ == null) { + proposal_ = null; + onChanged(); + } else { + proposal_ = null; + proposalBuilder_ = null; + } + + return this; + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + public pactus.blockchain.BlockchainOuterClass.Proposal.Builder getProposalBuilder() { + + onChanged(); + return getProposalFieldBuilder().getBuilder(); + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + public pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder() { + if (proposalBuilder_ != null) { + return proposalBuilder_.getMessageOrBuilder(); + } else { + return proposal_ == null ? + pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; + } + } + /** + *
                  +       * The proposal of the consensus info.
                  +       * 
                  + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + private com.google.protobuf.SingleFieldBuilderV3< + pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder> + getProposalFieldBuilder() { + if (proposalBuilder_ == null) { + proposalBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder>( + getProposal(), + getParentForChildren(), + isClean()); + proposal_ = null; + } + return proposalBuilder_; + } + private java.util.List instances_ = java.util.Collections.emptyList(); private void ensureInstancesIsMutable() { @@ -13686,7 +13841,7 @@ private void ensureInstancesIsMutable() { * List of consensus instances. *
                  * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public java.util.List getInstancesList() { if (instancesBuilder_ == null) { @@ -13700,7 +13855,7 @@ public java.util.List getI * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public int getInstancesCount() { if (instancesBuilder_ == null) { @@ -13714,7 +13869,7 @@ public int getInstancesCount() { * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int index) { if (instancesBuilder_ == null) { @@ -13728,7 +13883,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int ind * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder setInstances( int index, pactus.blockchain.BlockchainOuterClass.ConsensusInfo value) { @@ -13749,7 +13904,7 @@ public Builder setInstances( * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder setInstances( int index, pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder builderForValue) { @@ -13767,7 +13922,7 @@ public Builder setInstances( * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder addInstances(pactus.blockchain.BlockchainOuterClass.ConsensusInfo value) { if (instancesBuilder_ == null) { @@ -13787,7 +13942,7 @@ public Builder addInstances(pactus.blockchain.BlockchainOuterClass.ConsensusInfo * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder addInstances( int index, pactus.blockchain.BlockchainOuterClass.ConsensusInfo value) { @@ -13808,7 +13963,7 @@ public Builder addInstances( * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder addInstances( pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder builderForValue) { @@ -13826,7 +13981,7 @@ public Builder addInstances( * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder addInstances( int index, pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder builderForValue) { @@ -13844,7 +13999,7 @@ public Builder addInstances( * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder addAllInstances( java.lang.Iterable values) { @@ -13863,7 +14018,7 @@ public Builder addAllInstances( * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder clearInstances() { if (instancesBuilder_ == null) { @@ -13880,7 +14035,7 @@ public Builder clearInstances() { * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public Builder removeInstances(int index) { if (instancesBuilder_ == null) { @@ -13897,7 +14052,7 @@ public Builder removeInstances(int index) { * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder getInstancesBuilder( int index) { @@ -13908,7 +14063,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder getInstances * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( int index) { @@ -13922,7 +14077,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstance * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public java.util.List getInstancesOrBuilderList() { @@ -13937,7 +14092,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstance * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder addInstancesBuilder() { return getInstancesFieldBuilder().addBuilder( @@ -13948,7 +14103,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder addInstances * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder addInstancesBuilder( int index) { @@ -13960,7 +14115,7 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder addInstances * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ public java.util.List getInstancesBuilderList() { @@ -13980,161 +14135,6 @@ public pactus.blockchain.BlockchainOuterClass.ConsensusInfo.Builder addInstances } return instancesBuilder_; } - - private pactus.blockchain.BlockchainOuterClass.Proposal proposal_; - private com.google.protobuf.SingleFieldBuilderV3< - pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder> proposalBuilder_; - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - * @return Whether the proposal field is set. - */ - public boolean hasProposal() { - return proposalBuilder_ != null || proposal_ != null; - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - * @return The proposal. - */ - public pactus.blockchain.BlockchainOuterClass.Proposal getProposal() { - if (proposalBuilder_ == null) { - return proposal_ == null ? pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; - } else { - return proposalBuilder_.getMessage(); - } - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - public Builder setProposal(pactus.blockchain.BlockchainOuterClass.Proposal value) { - if (proposalBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - proposal_ = value; - onChanged(); - } else { - proposalBuilder_.setMessage(value); - } - - return this; - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - public Builder setProposal( - pactus.blockchain.BlockchainOuterClass.Proposal.Builder builderForValue) { - if (proposalBuilder_ == null) { - proposal_ = builderForValue.build(); - onChanged(); - } else { - proposalBuilder_.setMessage(builderForValue.build()); - } - - return this; - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - public Builder mergeProposal(pactus.blockchain.BlockchainOuterClass.Proposal value) { - if (proposalBuilder_ == null) { - if (proposal_ != null) { - proposal_ = - pactus.blockchain.BlockchainOuterClass.Proposal.newBuilder(proposal_).mergeFrom(value).buildPartial(); - } else { - proposal_ = value; - } - onChanged(); - } else { - proposalBuilder_.mergeFrom(value); - } - - return this; - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - public Builder clearProposal() { - if (proposalBuilder_ == null) { - proposal_ = null; - onChanged(); - } else { - proposal_ = null; - proposalBuilder_ = null; - } - - return this; - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - public pactus.blockchain.BlockchainOuterClass.Proposal.Builder getProposalBuilder() { - - onChanged(); - return getProposalFieldBuilder().getBuilder(); - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - public pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder getProposalOrBuilder() { - if (proposalBuilder_ != null) { - return proposalBuilder_.getMessageOrBuilder(); - } else { - return proposal_ == null ? - pactus.blockchain.BlockchainOuterClass.Proposal.getDefaultInstance() : proposal_; - } - } - /** - *
                  -       * The proposal of the consensus info.
                  -       * 
                  - * - * .pactus.Proposal proposal = 6 [json_name = "proposal"]; - */ - private com.google.protobuf.SingleFieldBuilderV3< - pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder> - getProposalFieldBuilder() { - if (proposalBuilder_ == null) { - proposalBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - pactus.blockchain.BlockchainOuterClass.Proposal, pactus.blockchain.BlockchainOuterClass.Proposal.Builder, pactus.blockchain.BlockchainOuterClass.ProposalOrBuilder>( - getProposal(), - getParentForChildren(), - isClean()); - proposal_ = null; - } - return proposalBuilder_; - } @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -24764,9 +24764,9 @@ public pactus.blockchain.BlockchainOuterClass.Proposal getDefaultInstanceForType "sPruned\022%\n\016pruning_height\030\t \001(\rR\rpruning" + "Height\022&\n\017last_block_time\030\n \001(\003R\rlastBlo" + "ckTime\"\031\n\027GetConsensusInfoRequest\"}\n\030Get" + - "ConsensusInfoResponse\0223\n\tinstances\030\001 \003(\013" + - "2\025.pactus.ConsensusInfoR\tinstances\022,\n\010pr" + - "oposal\030\006 \001(\0132\020.pactus.ProposalR\010proposal" + + "ConsensusInfoResponse\022,\n\010proposal\030\001 \001(\0132" + + "\020.pactus.ProposalR\010proposal\0223\n\tinstances" + + "\030\002 \003(\0132\025.pactus.ConsensusInfoR\tinstances" + "\"Q\n\027GetTxPoolContentRequest\0226\n\014payload_t" + "ype\030\001 \001(\0162\023.pactus.PayloadTypeR\013payloadT" + "ype\"E\n\030GetTxPoolContentResponse\022)\n\003txs\030\001" + @@ -24952,7 +24952,7 @@ public pactus.blockchain.BlockchainOuterClass.Proposal getDefaultInstanceForType internal_static_pactus_GetConsensusInfoResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_pactus_GetConsensusInfoResponse_descriptor, - new java.lang.String[] { "Instances", "Proposal", }); + new java.lang.String[] { "Proposal", "Instances", }); internal_static_pactus_GetTxPoolContentRequest_descriptor = getDescriptor().getMessageTypes().get(19); internal_static_pactus_GetTxPoolContentRequest_fieldAccessorTable = new diff --git a/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java b/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java index 9cf8b97d7..6e9fad838 100644 --- a/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java +++ b/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java @@ -48,6 +48,15 @@ public enum AddressType * ADDRESS_TYPE_BLS_ACCOUNT = 2; */ ADDRESS_TYPE_BLS_ACCOUNT(2), + /** + *
                  +     * Account address type with Ed25519 signature scheme.
                  +     * Note: Generating a new Ed25519 address requires the wallet password.
                  +     * 
                  + * + * ADDRESS_TYPE_ED25519_ACCOUNT = 3; + */ + ADDRESS_TYPE_ED25519_ACCOUNT(3), UNRECOGNIZED(-1), ; @@ -76,6 +85,15 @@ public enum AddressType * ADDRESS_TYPE_BLS_ACCOUNT = 2; */ public static final int ADDRESS_TYPE_BLS_ACCOUNT_VALUE = 2; + /** + *
                  +     * Account address type with Ed25519 signature scheme.
                  +     * Note: Generating a new Ed25519 address requires the wallet password.
                  +     * 
                  + * + * ADDRESS_TYPE_ED25519_ACCOUNT = 3; + */ + public static final int ADDRESS_TYPE_ED25519_ACCOUNT_VALUE = 3; public final int getNumber() { @@ -105,6 +123,7 @@ public static AddressType forNumber(int value) { case 0: return ADDRESS_TYPE_TREASURY; case 1: return ADDRESS_TYPE_VALIDATOR; case 2: return ADDRESS_TYPE_BLS_ACCOUNT; + case 3: return ADDRESS_TYPE_ED25519_ACCOUNT; default: return null; } } @@ -4188,6 +4207,26 @@ public interface GetNewAddressRequestOrBuilder extends */ com.google.protobuf.ByteString getLabelBytes(); + + /** + *
                  +     * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +     * 
                  + * + * string password = 4 [json_name = "password"]; + * @return The password. + */ + java.lang.String getPassword(); + /** + *
                  +     * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +     * 
                  + * + * string password = 4 [json_name = "password"]; + * @return The bytes for password. + */ + com.google.protobuf.ByteString + getPasswordBytes(); } /** *
                  @@ -4209,6 +4248,7 @@ private GetNewAddressRequest() {
                         walletName_ = "";
                         addressType_ = 0;
                         label_ = "";
                  +      password_ = "";
                       }
                   
                       @java.lang.Override
                  @@ -4355,6 +4395,52 @@ public java.lang.String getLabel() {
                         }
                       }
                   
                  +    public static final int PASSWORD_FIELD_NUMBER = 4;
                  +    private volatile java.lang.Object password_;
                  +    /**
                  +     * 
                  +     * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +     * 
                  + * + * string password = 4 [json_name = "password"]; + * @return The password. + */ + @java.lang.Override + public java.lang.String getPassword() { + java.lang.Object ref = password_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + password_ = s; + return s; + } + } + /** + *
                  +     * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +     * 
                  + * + * string password = 4 [json_name = "password"]; + * @return The bytes for password. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getPasswordBytes() { + java.lang.Object ref = password_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + password_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -4378,6 +4464,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(label_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 3, label_); } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(password_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, password_); + } getUnknownFields().writeTo(output); } @@ -4397,6 +4486,9 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(label_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, label_); } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(password_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, password_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -4417,6 +4509,8 @@ public boolean equals(final java.lang.Object obj) { if (addressType_ != other.addressType_) return false; if (!getLabel() .equals(other.getLabel())) return false; + if (!getPassword() + .equals(other.getPassword())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -4434,6 +4528,8 @@ public int hashCode() { hash = (53 * hash) + addressType_; hash = (37 * hash) + LABEL_FIELD_NUMBER; hash = (53 * hash) + getLabel().hashCode(); + hash = (37 * hash) + PASSWORD_FIELD_NUMBER; + hash = (53 * hash) + getPassword().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -4572,6 +4668,8 @@ public Builder clear() { label_ = ""; + password_ = ""; + return this; } @@ -4601,6 +4699,7 @@ public pactus.wallet.WalletOuterClass.GetNewAddressRequest buildPartial() { result.walletName_ = walletName_; result.addressType_ = addressType_; result.label_ = label_; + result.password_ = password_; onBuilt(); return result; } @@ -4660,6 +4759,10 @@ public Builder mergeFrom(pactus.wallet.WalletOuterClass.GetNewAddressRequest oth label_ = other.label_; onChanged(); } + if (!other.getPassword().isEmpty()) { + password_ = other.password_; + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -4701,6 +4804,11 @@ public Builder mergeFrom( break; } // case 26 + case 34: { + password_ = input.readStringRequireUtf8(); + + break; + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -4982,6 +5090,102 @@ public Builder setLabelBytes( onChanged(); return this; } + + private java.lang.Object password_ = ""; + /** + *
                  +       * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +       * 
                  + * + * string password = 4 [json_name = "password"]; + * @return The password. + */ + public java.lang.String getPassword() { + java.lang.Object ref = password_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + password_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
                  +       * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +       * 
                  + * + * string password = 4 [json_name = "password"]; + * @return The bytes for password. + */ + public com.google.protobuf.ByteString + getPasswordBytes() { + java.lang.Object ref = password_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + password_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
                  +       * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +       * 
                  + * + * string password = 4 [json_name = "password"]; + * @param value The password to set. + * @return This builder for chaining. + */ + public Builder setPassword( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + password_ = value; + onChanged(); + return this; + } + /** + *
                  +       * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +       * 
                  + * + * string password = 4 [json_name = "password"]; + * @return This builder for chaining. + */ + public Builder clearPassword() { + + password_ = getDefaultInstance().getPassword(); + onChanged(); + return this; + } + /** + *
                  +       * Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.
                  +       * 
                  + * + * string password = 4 [json_name = "password"]; + * @param value The bytes for password to set. + * @return This builder for chaining. + */ + public Builder setPasswordBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + password_ = value; + onChanged(); + return this; + } @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -17275,69 +17479,71 @@ public pactus.wallet.WalletOuterClass.SignMessageResponse getDefaultInstanceForT "t_name\030\001 \001(\tR\nwalletName\022\030\n\007address\030\002 \001(" + "\tR\007address\"S\n\031GetAddressHistoryResponse\022" + "6\n\014history_info\030\001 \003(\0132\023.pactus.HistoryIn" + - "foR\013historyInfo\"\205\001\n\024GetNewAddressRequest" + + "foR\013historyInfo\"\241\001\n\024GetNewAddressRequest" + "\022\037\n\013wallet_name\030\001 \001(\tR\nwalletName\0226\n\014add" + "ress_type\030\002 \001(\0162\023.pactus.AddressTypeR\013ad" + - "dressType\022\024\n\005label\030\003 \001(\tR\005label\"p\n\025GetNe" + - "wAddressResponse\022\037\n\013wallet_name\030\001 \001(\tR\nw" + - "alletName\0226\n\014address_info\030\002 \001(\0132\023.pactus" + - ".AddressInfoR\013addressInfo\"o\n\024RestoreWall" + - "etRequest\022\037\n\013wallet_name\030\001 \001(\tR\nwalletNa" + - "me\022\032\n\010mnemonic\030\002 \001(\tR\010mnemonic\022\032\n\010passwo" + - "rd\030\003 \001(\tR\010password\"8\n\025RestoreWalletRespo" + - "nse\022\037\n\013wallet_name\030\001 \001(\tR\nwalletName\"R\n\023" + - "CreateWalletRequest\022\037\n\013wallet_name\030\001 \001(\t" + - "R\nwalletName\022\032\n\010password\030\004 \001(\tR\010password" + - "\"2\n\024CreateWalletResponse\022\032\n\010mnemonic\030\002 \001" + - "(\tR\010mnemonic\"4\n\021LoadWalletRequest\022\037\n\013wal" + - "let_name\030\001 \001(\tR\nwalletName\"5\n\022LoadWallet" + - "Response\022\037\n\013wallet_name\030\001 \001(\tR\nwalletNam" + - "e\"6\n\023UnloadWalletRequest\022\037\n\013wallet_name\030" + - "\001 \001(\tR\nwalletName\"7\n\024UnloadWalletRespons" + - "e\022\037\n\013wallet_name\030\001 \001(\tR\nwalletName\";\n\032Ge" + - "tValidatorAddressRequest\022\035\n\npublic_key\030\001" + - " \001(\tR\tpublicKey\"7\n\033GetValidatorAddressRe" + - "sponse\022\030\n\007address\030\001 \001(\tR\007address\"\201\001\n\031Sig" + - "nRawTransactionRequest\022\037\n\013wallet_name\030\001 " + - "\001(\tR\nwalletName\022\'\n\017raw_transaction\030\002 \001(\t" + - "R\016rawTransaction\022\032\n\010password\030\003 \001(\tR\010pass" + - "word\"y\n\032SignRawTransactionResponse\022%\n\016tr" + - "ansaction_id\030\001 \001(\tR\rtransactionId\0224\n\026sig" + - "ned_raw_transaction\030\002 \001(\tR\024signedRawTran" + - "saction\"9\n\026GetTotalBalanceRequest\022\037\n\013wal" + - "let_name\030\001 \001(\tR\nwalletName\"_\n\027GetTotalBa" + - "lanceResponse\022\037\n\013wallet_name\030\001 \001(\tR\nwall" + - "etName\022#\n\rtotal_balance\030\002 \001(\003R\014totalBala" + - "nce\"\205\001\n\022SignMessageRequest\022\037\n\013wallet_nam" + - "e\030\001 \001(\tR\nwalletName\022\032\n\010password\030\002 \001(\tR\010p" + - "assword\022\030\n\007address\030\003 \001(\tR\007address\022\030\n\007mes" + - "sage\030\004 \001(\tR\007message\"3\n\023SignMessageRespon" + - "se\022\034\n\tsignature\030\001 \001(\tR\tsignature*b\n\013Addr" + - "essType\022\031\n\025ADDRESS_TYPE_TREASURY\020\000\022\032\n\026AD" + - "DRESS_TYPE_VALIDATOR\020\001\022\034\n\030ADDRESS_TYPE_B" + - "LS_ACCOUNT\020\0022\262\006\n\006Wallet\022I\n\014CreateWallet\022" + - "\033.pactus.CreateWalletRequest\032\034.pactus.Cr" + - "eateWalletResponse\022L\n\rRestoreWallet\022\034.pa" + - "ctus.RestoreWalletRequest\032\035.pactus.Resto" + - "reWalletResponse\022C\n\nLoadWallet\022\031.pactus." + - "LoadWalletRequest\032\032.pactus.LoadWalletRes" + - "ponse\022I\n\014UnloadWallet\022\033.pactus.UnloadWal" + - "letRequest\032\034.pactus.UnloadWalletResponse" + - "\022R\n\017GetTotalBalance\022\036.pactus.GetTotalBal" + - "anceRequest\032\037.pactus.GetTotalBalanceResp" + - "onse\022[\n\022SignRawTransaction\022!.pactus.Sign" + - "RawTransactionRequest\032\".pactus.SignRawTr" + - "ansactionResponse\022^\n\023GetValidatorAddress" + - "\022\".pactus.GetValidatorAddressRequest\032#.p" + - "actus.GetValidatorAddressResponse\022L\n\rGet" + - "NewAddress\022\034.pactus.GetNewAddressRequest" + - "\032\035.pactus.GetNewAddressResponse\022X\n\021GetAd" + - "dressHistory\022 .pactus.GetAddressHistoryR" + - "equest\032!.pactus.GetAddressHistoryRespons" + - "e\022F\n\013SignMessage\022\032.pactus.SignMessageReq" + - "uest\032\033.pactus.SignMessageResponseBA\n\rpac" + - "tus.walletZ0github.com/pactus-project/pa" + - "ctus/www/grpc/pactusb\006proto3" + "dressType\022\024\n\005label\030\003 \001(\tR\005label\022\032\n\010passw" + + "ord\030\004 \001(\tR\010password\"p\n\025GetNewAddressResp" + + "onse\022\037\n\013wallet_name\030\001 \001(\tR\nwalletName\0226\n" + + "\014address_info\030\002 \001(\0132\023.pactus.AddressInfo" + + "R\013addressInfo\"o\n\024RestoreWalletRequest\022\037\n" + + "\013wallet_name\030\001 \001(\tR\nwalletName\022\032\n\010mnemon" + + "ic\030\002 \001(\tR\010mnemonic\022\032\n\010password\030\003 \001(\tR\010pa" + + "ssword\"8\n\025RestoreWalletResponse\022\037\n\013walle" + + "t_name\030\001 \001(\tR\nwalletName\"R\n\023CreateWallet" + + "Request\022\037\n\013wallet_name\030\001 \001(\tR\nwalletName" + + "\022\032\n\010password\030\004 \001(\tR\010password\"2\n\024CreateWa" + + "lletResponse\022\032\n\010mnemonic\030\002 \001(\tR\010mnemonic" + + "\"4\n\021LoadWalletRequest\022\037\n\013wallet_name\030\001 \001" + + "(\tR\nwalletName\"5\n\022LoadWalletResponse\022\037\n\013" + + "wallet_name\030\001 \001(\tR\nwalletName\"6\n\023UnloadW" + + "alletRequest\022\037\n\013wallet_name\030\001 \001(\tR\nwalle" + + "tName\"7\n\024UnloadWalletResponse\022\037\n\013wallet_" + + "name\030\001 \001(\tR\nwalletName\";\n\032GetValidatorAd" + + "dressRequest\022\035\n\npublic_key\030\001 \001(\tR\tpublic" + + "Key\"7\n\033GetValidatorAddressResponse\022\030\n\007ad" + + "dress\030\001 \001(\tR\007address\"\201\001\n\031SignRawTransact" + + "ionRequest\022\037\n\013wallet_name\030\001 \001(\tR\nwalletN" + + "ame\022\'\n\017raw_transaction\030\002 \001(\tR\016rawTransac" + + "tion\022\032\n\010password\030\003 \001(\tR\010password\"y\n\032Sign" + + "RawTransactionResponse\022%\n\016transaction_id" + + "\030\001 \001(\tR\rtransactionId\0224\n\026signed_raw_tran" + + "saction\030\002 \001(\tR\024signedRawTransaction\"9\n\026G" + + "etTotalBalanceRequest\022\037\n\013wallet_name\030\001 \001" + + "(\tR\nwalletName\"_\n\027GetTotalBalanceRespons" + + "e\022\037\n\013wallet_name\030\001 \001(\tR\nwalletName\022#\n\rto" + + "tal_balance\030\002 \001(\003R\014totalBalance\"\205\001\n\022Sign" + + "MessageRequest\022\037\n\013wallet_name\030\001 \001(\tR\nwal" + + "letName\022\032\n\010password\030\002 \001(\tR\010password\022\030\n\007a" + + "ddress\030\003 \001(\tR\007address\022\030\n\007message\030\004 \001(\tR\007" + + "message\"3\n\023SignMessageResponse\022\034\n\tsignat" + + "ure\030\001 \001(\tR\tsignature*\204\001\n\013AddressType\022\031\n\025" + + "ADDRESS_TYPE_TREASURY\020\000\022\032\n\026ADDRESS_TYPE_" + + "VALIDATOR\020\001\022\034\n\030ADDRESS_TYPE_BLS_ACCOUNT\020" + + "\002\022 \n\034ADDRESS_TYPE_ED25519_ACCOUNT\020\0032\262\006\n\006" + + "Wallet\022I\n\014CreateWallet\022\033.pactus.CreateWa" + + "lletRequest\032\034.pactus.CreateWalletRespons" + + "e\022L\n\rRestoreWallet\022\034.pactus.RestoreWalle" + + "tRequest\032\035.pactus.RestoreWalletResponse\022" + + "C\n\nLoadWallet\022\031.pactus.LoadWalletRequest" + + "\032\032.pactus.LoadWalletResponse\022I\n\014UnloadWa" + + "llet\022\033.pactus.UnloadWalletRequest\032\034.pact" + + "us.UnloadWalletResponse\022R\n\017GetTotalBalan" + + "ce\022\036.pactus.GetTotalBalanceRequest\032\037.pac" + + "tus.GetTotalBalanceResponse\022[\n\022SignRawTr" + + "ansaction\022!.pactus.SignRawTransactionReq" + + "uest\032\".pactus.SignRawTransactionResponse" + + "\022^\n\023GetValidatorAddress\022\".pactus.GetVali" + + "datorAddressRequest\032#.pactus.GetValidato" + + "rAddressResponse\022L\n\rGetNewAddress\022\034.pact" + + "us.GetNewAddressRequest\032\035.pactus.GetNewA" + + "ddressResponse\022X\n\021GetAddressHistory\022 .pa" + + "ctus.GetAddressHistoryRequest\032!.pactus.G" + + "etAddressHistoryResponse\022F\n\013SignMessage\022" + + "\032.pactus.SignMessageRequest\032\033.pactus.Sig" + + "nMessageResponseBA\n\rpactus.walletZ0githu" + + "b.com/pactus-project/pactus/www/grpc/pac" + + "tusb\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -17373,7 +17579,7 @@ public pactus.wallet.WalletOuterClass.SignMessageResponse getDefaultInstanceForT internal_static_pactus_GetNewAddressRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_pactus_GetNewAddressRequest_descriptor, - new java.lang.String[] { "WalletName", "AddressType", "Label", }); + new java.lang.String[] { "WalletName", "AddressType", "Label", "Password", }); internal_static_pactus_GetNewAddressResponse_descriptor = getDescriptor().getMessageTypes().get(5); internal_static_pactus_GetNewAddressResponse_fieldAccessorTable = new diff --git a/www/grpc/gen/js/blockchain_pb.js b/www/grpc/gen/js/blockchain_pb.js index e9f2d347e..4a3457f9b 100644 --- a/www/grpc/gen/js/blockchain_pb.js +++ b/www/grpc/gen/js/blockchain_pb.js @@ -3550,7 +3550,7 @@ proto.pactus.GetConsensusInfoRequest.serializeBinaryToWriter = function(message, * @private {!Array} * @const */ -proto.pactus.GetConsensusInfoResponse.repeatedFields_ = [1]; +proto.pactus.GetConsensusInfoResponse.repeatedFields_ = [2]; @@ -3583,9 +3583,9 @@ proto.pactus.GetConsensusInfoResponse.prototype.toObject = function(opt_includeI */ proto.pactus.GetConsensusInfoResponse.toObject = function(includeInstance, msg) { var f, obj = { + proposal: (f = msg.getProposal()) && proto.pactus.Proposal.toObject(includeInstance, f), instancesList: jspb.Message.toObjectList(msg.getInstancesList(), - proto.pactus.ConsensusInfo.toObject, includeInstance), - proposal: (f = msg.getProposal()) && proto.pactus.Proposal.toObject(includeInstance, f) + proto.pactus.ConsensusInfo.toObject, includeInstance) }; if (includeInstance) { @@ -3623,15 +3623,15 @@ proto.pactus.GetConsensusInfoResponse.deserializeBinaryFromReader = function(msg var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.pactus.ConsensusInfo; - reader.readMessage(value,proto.pactus.ConsensusInfo.deserializeBinaryFromReader); - msg.addInstances(value); - break; - case 6: var value = new proto.pactus.Proposal; reader.readMessage(value,proto.pactus.Proposal.deserializeBinaryFromReader); msg.setProposal(value); break; + case 2: + var value = new proto.pactus.ConsensusInfo; + reader.readMessage(value,proto.pactus.ConsensusInfo.deserializeBinaryFromReader); + msg.addInstances(value); + break; default: reader.skipField(); break; @@ -3661,97 +3661,97 @@ proto.pactus.GetConsensusInfoResponse.prototype.serializeBinary = function() { */ proto.pactus.GetConsensusInfoResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getInstancesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 1, - f, - proto.pactus.ConsensusInfo.serializeBinaryToWriter - ); - } f = message.getProposal(); if (f != null) { writer.writeMessage( - 6, + 1, f, proto.pactus.Proposal.serializeBinaryToWriter ); } + f = message.getInstancesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.pactus.ConsensusInfo.serializeBinaryToWriter + ); + } }; /** - * repeated ConsensusInfo instances = 1; - * @return {!Array} + * optional Proposal proposal = 1; + * @return {?proto.pactus.Proposal} */ -proto.pactus.GetConsensusInfoResponse.prototype.getInstancesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.pactus.ConsensusInfo, 1)); +proto.pactus.GetConsensusInfoResponse.prototype.getProposal = function() { + return /** @type{?proto.pactus.Proposal} */ ( + jspb.Message.getWrapperField(this, proto.pactus.Proposal, 1)); }; /** - * @param {!Array} value + * @param {?proto.pactus.Proposal|undefined} value * @return {!proto.pactus.GetConsensusInfoResponse} returns this */ -proto.pactus.GetConsensusInfoResponse.prototype.setInstancesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); +proto.pactus.GetConsensusInfoResponse.prototype.setProposal = function(value) { + return jspb.Message.setWrapperField(this, 1, value); }; /** - * @param {!proto.pactus.ConsensusInfo=} opt_value - * @param {number=} opt_index - * @return {!proto.pactus.ConsensusInfo} + * Clears the message field making it undefined. + * @return {!proto.pactus.GetConsensusInfoResponse} returns this */ -proto.pactus.GetConsensusInfoResponse.prototype.addInstances = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.pactus.ConsensusInfo, opt_index); +proto.pactus.GetConsensusInfoResponse.prototype.clearProposal = function() { + return this.setProposal(undefined); }; /** - * Clears the list making it empty but non-null. - * @return {!proto.pactus.GetConsensusInfoResponse} returns this + * Returns whether this field is set. + * @return {boolean} */ -proto.pactus.GetConsensusInfoResponse.prototype.clearInstancesList = function() { - return this.setInstancesList([]); +proto.pactus.GetConsensusInfoResponse.prototype.hasProposal = function() { + return jspb.Message.getField(this, 1) != null; }; /** - * optional Proposal proposal = 6; - * @return {?proto.pactus.Proposal} + * repeated ConsensusInfo instances = 2; + * @return {!Array} */ -proto.pactus.GetConsensusInfoResponse.prototype.getProposal = function() { - return /** @type{?proto.pactus.Proposal} */ ( - jspb.Message.getWrapperField(this, proto.pactus.Proposal, 6)); +proto.pactus.GetConsensusInfoResponse.prototype.getInstancesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.pactus.ConsensusInfo, 2)); }; /** - * @param {?proto.pactus.Proposal|undefined} value + * @param {!Array} value * @return {!proto.pactus.GetConsensusInfoResponse} returns this */ -proto.pactus.GetConsensusInfoResponse.prototype.setProposal = function(value) { - return jspb.Message.setWrapperField(this, 6, value); +proto.pactus.GetConsensusInfoResponse.prototype.setInstancesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); }; /** - * Clears the message field making it undefined. - * @return {!proto.pactus.GetConsensusInfoResponse} returns this + * @param {!proto.pactus.ConsensusInfo=} opt_value + * @param {number=} opt_index + * @return {!proto.pactus.ConsensusInfo} */ -proto.pactus.GetConsensusInfoResponse.prototype.clearProposal = function() { - return this.setProposal(undefined); +proto.pactus.GetConsensusInfoResponse.prototype.addInstances = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.pactus.ConsensusInfo, opt_index); }; /** - * Returns whether this field is set. - * @return {boolean} + * Clears the list making it empty but non-null. + * @return {!proto.pactus.GetConsensusInfoResponse} returns this */ -proto.pactus.GetConsensusInfoResponse.prototype.hasProposal = function() { - return jspb.Message.getField(this, 6) != null; +proto.pactus.GetConsensusInfoResponse.prototype.clearInstancesList = function() { + return this.setInstancesList([]); }; diff --git a/www/grpc/gen/js/wallet_pb.js b/www/grpc/gen/js/wallet_pb.js index 4e53e90ea..af1e74bb4 100644 --- a/www/grpc/gen/js/wallet_pb.js +++ b/www/grpc/gen/js/wallet_pb.js @@ -1332,7 +1332,8 @@ proto.pactus.GetNewAddressRequest.toObject = function(includeInstance, msg) { var f, obj = { walletName: jspb.Message.getFieldWithDefault(msg, 1, ""), addressType: jspb.Message.getFieldWithDefault(msg, 2, 0), - label: jspb.Message.getFieldWithDefault(msg, 3, "") + label: jspb.Message.getFieldWithDefault(msg, 3, ""), + password: jspb.Message.getFieldWithDefault(msg, 4, "") }; if (includeInstance) { @@ -1381,6 +1382,10 @@ proto.pactus.GetNewAddressRequest.deserializeBinaryFromReader = function(msg, re var value = /** @type {string} */ (reader.readString()); msg.setLabel(value); break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setPassword(value); + break; default: reader.skipField(); break; @@ -1431,6 +1436,13 @@ proto.pactus.GetNewAddressRequest.serializeBinaryToWriter = function(message, wr f ); } + f = message.getPassword(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } }; @@ -1488,6 +1500,24 @@ proto.pactus.GetNewAddressRequest.prototype.setLabel = function(value) { }; +/** + * optional string password = 4; + * @return {string} + */ +proto.pactus.GetNewAddressRequest.prototype.getPassword = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.pactus.GetNewAddressRequest} returns this + */ +proto.pactus.GetNewAddressRequest.prototype.setPassword = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); +}; + + @@ -4055,7 +4085,8 @@ proto.pactus.SignMessageResponse.prototype.setSignature = function(value) { proto.pactus.AddressType = { ADDRESS_TYPE_TREASURY: 0, ADDRESS_TYPE_VALIDATOR: 1, - ADDRESS_TYPE_BLS_ACCOUNT: 2 + ADDRESS_TYPE_BLS_ACCOUNT: 2, + ADDRESS_TYPE_ED25519_ACCOUNT: 3 }; goog.object.extend(exports, proto.pactus); diff --git a/www/grpc/gen/python/blockchain_pb2.py b/www/grpc/gen/python/blockchain_pb2.py index f79c1ad09..71699b150 100644 --- a/www/grpc/gen/python/blockchain_pb2.py +++ b/www/grpc/gen/python/blockchain_pb2.py @@ -14,7 +14,7 @@ import transaction_pb2 as transaction__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x62lockchain.proto\x12\x06pactus\x1a\x11transaction.proto\"-\n\x11GetAccountRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"C\n\x12GetAccountResponse\x12-\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x13.pactus.AccountInfoR\x07\x61\x63\x63ount\"\x1e\n\x1cGetValidatorAddressesRequest\"=\n\x1dGetValidatorAddressesResponse\x12\x1c\n\taddresses\x18\x01 \x03(\tR\taddresses\"/\n\x13GetValidatorRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x1bGetValidatorByNumberRequest\x12\x16\n\x06number\x18\x01 \x01(\x05R\x06number\"K\n\x14GetValidatorResponse\x12\x33\n\tvalidator\x18\x01 \x01(\x0b\x32\x15.pactus.ValidatorInfoR\tvalidator\"/\n\x13GetPublicKeyRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x14GetPublicKeyResponse\x12\x1d\n\npublic_key\x18\x01 \x01(\tR\tpublicKey\"_\n\x0fGetBlockRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x34\n\tverbosity\x18\x02 \x01(\x0e\x32\x16.pactus.BlockVerbosityR\tverbosity\"\x83\x02\n\x10GetBlockResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x12\n\x04hash\x18\x02 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x03 \x01(\tR\x04\x64\x61ta\x12\x1d\n\nblock_time\x18\x04 \x01(\rR\tblockTime\x12/\n\x06header\x18\x05 \x01(\x0b\x32\x17.pactus.BlockHeaderInfoR\x06header\x12\x34\n\tprev_cert\x18\x06 \x01(\x0b\x32\x17.pactus.CertificateInfoR\x08prevCert\x12)\n\x03txs\x18\x07 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"-\n\x13GetBlockHashRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"*\n\x14GetBlockHashResponse\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"+\n\x15GetBlockHeightRequest\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"0\n\x16GetBlockHeightResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"\x1a\n\x18GetBlockchainInfoRequest\"\xc1\x03\n\x19GetBlockchainInfoResponse\x12*\n\x11last_block_height\x18\x01 \x01(\rR\x0flastBlockHeight\x12&\n\x0flast_block_hash\x18\x02 \x01(\tR\rlastBlockHash\x12%\n\x0etotal_accounts\x18\x03 \x01(\x05R\rtotalAccounts\x12)\n\x10total_validators\x18\x04 \x01(\x05R\x0ftotalValidators\x12\x1f\n\x0btotal_power\x18\x05 \x01(\x03R\ntotalPower\x12\'\n\x0f\x63ommittee_power\x18\x06 \x01(\x03R\x0e\x63ommitteePower\x12H\n\x14\x63ommittee_validators\x18\x07 \x03(\x0b\x32\x15.pactus.ValidatorInfoR\x13\x63ommitteeValidators\x12\x1b\n\tis_pruned\x18\x08 \x01(\x08R\x08isPruned\x12%\n\x0epruning_height\x18\t \x01(\rR\rpruningHeight\x12&\n\x0flast_block_time\x18\n \x01(\x03R\rlastBlockTime\"\x19\n\x17GetConsensusInfoRequest\"}\n\x18GetConsensusInfoResponse\x12\x33\n\tinstances\x18\x01 \x03(\x0b\x32\x15.pactus.ConsensusInfoR\tinstances\x12,\n\x08proposal\x18\x06 \x01(\x0b\x32\x10.pactus.ProposalR\x08proposal\"Q\n\x17GetTxPoolContentRequest\x12\x36\n\x0cpayload_type\x18\x01 \x01(\x0e\x32\x13.pactus.PayloadTypeR\x0bpayloadType\"E\n\x18GetTxPoolContentResponse\x12)\n\x03txs\x18\x01 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"\xdc\x02\n\rValidatorInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x1d\n\npublic_key\x18\x03 \x01(\tR\tpublicKey\x12\x16\n\x06number\x18\x04 \x01(\x05R\x06number\x12\x14\n\x05stake\x18\x05 \x01(\x03R\x05stake\x12.\n\x13last_bonding_height\x18\x06 \x01(\rR\x11lastBondingHeight\x12\x32\n\x15last_sortition_height\x18\x07 \x01(\rR\x13lastSortitionHeight\x12)\n\x10unbonding_height\x18\x08 \x01(\rR\x0funbondingHeight\x12\x18\n\x07\x61\x64\x64ress\x18\t \x01(\tR\x07\x61\x64\x64ress\x12-\n\x12\x61vailability_score\x18\n \x01(\x01R\x11\x61vailabilityScore\"\x81\x01\n\x0b\x41\x63\x63ountInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x16\n\x06number\x18\x03 \x01(\x05R\x06number\x12\x18\n\x07\x62\x61lance\x18\x04 \x01(\x03R\x07\x62\x61lance\x12\x18\n\x07\x61\x64\x64ress\x18\x05 \x01(\tR\x07\x61\x64\x64ress\"\xc4\x01\n\x0f\x42lockHeaderInfo\x12\x18\n\x07version\x18\x01 \x01(\x05R\x07version\x12&\n\x0fprev_block_hash\x18\x02 \x01(\tR\rprevBlockHash\x12\x1d\n\nstate_root\x18\x03 \x01(\tR\tstateRoot\x12%\n\x0esortition_seed\x18\x04 \x01(\tR\rsortitionSeed\x12)\n\x10proposer_address\x18\x05 \x01(\tR\x0fproposerAddress\"\x97\x01\n\x0f\x43\x65rtificateInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1e\n\ncommitters\x18\x03 \x03(\x05R\ncommitters\x12\x1c\n\tabsentees\x18\x04 \x03(\x05R\tabsentees\x12\x1c\n\tsignature\x18\x05 \x01(\tR\tsignature\"\xb1\x01\n\x08VoteInfo\x12$\n\x04type\x18\x01 \x01(\x0e\x32\x10.pactus.VoteTypeR\x04type\x12\x14\n\x05voter\x18\x02 \x01(\tR\x05voter\x12\x1d\n\nblock_hash\x18\x03 \x01(\tR\tblockHash\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12\x19\n\x08\x63p_round\x18\x05 \x01(\x05R\x07\x63pRound\x12\x19\n\x08\x63p_value\x18\x06 \x01(\x05R\x07\x63pValue\"\x97\x01\n\rConsensusInfo\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\x12\x16\n\x06\x61\x63tive\x18\x02 \x01(\x08R\x06\x61\x63tive\x12\x16\n\x06height\x18\x03 \x01(\rR\x06height\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12&\n\x05votes\x18\x05 \x03(\x0b\x32\x10.pactus.VoteInfoR\x05votes\"~\n\x08Proposal\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1d\n\nblock_data\x18\x03 \x01(\tR\tblockData\x12%\n\x0esignature_data\x18\x04 \x01(\tR\rsignatureData*H\n\x0e\x42lockVerbosity\x12\x0e\n\nBLOCK_DATA\x10\x00\x12\x0e\n\nBLOCK_INFO\x10\x01\x12\x16\n\x12\x42LOCK_TRANSACTIONS\x10\x02*\\\n\x08VoteType\x12\x10\n\x0cVOTE_UNKNOWN\x10\x00\x12\x10\n\x0cVOTE_PREPARE\x10\x01\x12\x12\n\x0eVOTE_PRECOMMIT\x10\x02\x12\x18\n\x14VOTE_CHANGE_PROPOSER\x10\x03\x32\x8b\x07\n\nBlockchain\x12=\n\x08GetBlock\x12\x17.pactus.GetBlockRequest\x1a\x18.pactus.GetBlockResponse\x12I\n\x0cGetBlockHash\x12\x1b.pactus.GetBlockHashRequest\x1a\x1c.pactus.GetBlockHashResponse\x12O\n\x0eGetBlockHeight\x12\x1d.pactus.GetBlockHeightRequest\x1a\x1e.pactus.GetBlockHeightResponse\x12X\n\x11GetBlockchainInfo\x12 .pactus.GetBlockchainInfoRequest\x1a!.pactus.GetBlockchainInfoResponse\x12U\n\x10GetConsensusInfo\x12\x1f.pactus.GetConsensusInfoRequest\x1a .pactus.GetConsensusInfoResponse\x12\x43\n\nGetAccount\x12\x19.pactus.GetAccountRequest\x1a\x1a.pactus.GetAccountResponse\x12I\n\x0cGetValidator\x12\x1b.pactus.GetValidatorRequest\x1a\x1c.pactus.GetValidatorResponse\x12Y\n\x14GetValidatorByNumber\x12#.pactus.GetValidatorByNumberRequest\x1a\x1c.pactus.GetValidatorResponse\x12\x64\n\x15GetValidatorAddresses\x12$.pactus.GetValidatorAddressesRequest\x1a%.pactus.GetValidatorAddressesResponse\x12I\n\x0cGetPublicKey\x12\x1b.pactus.GetPublicKeyRequest\x1a\x1c.pactus.GetPublicKeyResponse\x12U\n\x10GetTxPoolContent\x12\x1f.pactus.GetTxPoolContentRequest\x1a .pactus.GetTxPoolContentResponseBE\n\x11pactus.blockchainZ0github.com/pactus-project/pactus/www/grpc/pactusb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x62lockchain.proto\x12\x06pactus\x1a\x11transaction.proto\"-\n\x11GetAccountRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"C\n\x12GetAccountResponse\x12-\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x13.pactus.AccountInfoR\x07\x61\x63\x63ount\"\x1e\n\x1cGetValidatorAddressesRequest\"=\n\x1dGetValidatorAddressesResponse\x12\x1c\n\taddresses\x18\x01 \x03(\tR\taddresses\"/\n\x13GetValidatorRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x1bGetValidatorByNumberRequest\x12\x16\n\x06number\x18\x01 \x01(\x05R\x06number\"K\n\x14GetValidatorResponse\x12\x33\n\tvalidator\x18\x01 \x01(\x0b\x32\x15.pactus.ValidatorInfoR\tvalidator\"/\n\x13GetPublicKeyRequest\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"5\n\x14GetPublicKeyResponse\x12\x1d\n\npublic_key\x18\x01 \x01(\tR\tpublicKey\"_\n\x0fGetBlockRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x34\n\tverbosity\x18\x02 \x01(\x0e\x32\x16.pactus.BlockVerbosityR\tverbosity\"\x83\x02\n\x10GetBlockResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x12\n\x04hash\x18\x02 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x03 \x01(\tR\x04\x64\x61ta\x12\x1d\n\nblock_time\x18\x04 \x01(\rR\tblockTime\x12/\n\x06header\x18\x05 \x01(\x0b\x32\x17.pactus.BlockHeaderInfoR\x06header\x12\x34\n\tprev_cert\x18\x06 \x01(\x0b\x32\x17.pactus.CertificateInfoR\x08prevCert\x12)\n\x03txs\x18\x07 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"-\n\x13GetBlockHashRequest\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"*\n\x14GetBlockHashResponse\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"+\n\x15GetBlockHeightRequest\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\"0\n\x16GetBlockHeightResponse\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\"\x1a\n\x18GetBlockchainInfoRequest\"\xc1\x03\n\x19GetBlockchainInfoResponse\x12*\n\x11last_block_height\x18\x01 \x01(\rR\x0flastBlockHeight\x12&\n\x0flast_block_hash\x18\x02 \x01(\tR\rlastBlockHash\x12%\n\x0etotal_accounts\x18\x03 \x01(\x05R\rtotalAccounts\x12)\n\x10total_validators\x18\x04 \x01(\x05R\x0ftotalValidators\x12\x1f\n\x0btotal_power\x18\x05 \x01(\x03R\ntotalPower\x12\'\n\x0f\x63ommittee_power\x18\x06 \x01(\x03R\x0e\x63ommitteePower\x12H\n\x14\x63ommittee_validators\x18\x07 \x03(\x0b\x32\x15.pactus.ValidatorInfoR\x13\x63ommitteeValidators\x12\x1b\n\tis_pruned\x18\x08 \x01(\x08R\x08isPruned\x12%\n\x0epruning_height\x18\t \x01(\rR\rpruningHeight\x12&\n\x0flast_block_time\x18\n \x01(\x03R\rlastBlockTime\"\x19\n\x17GetConsensusInfoRequest\"}\n\x18GetConsensusInfoResponse\x12,\n\x08proposal\x18\x01 \x01(\x0b\x32\x10.pactus.ProposalR\x08proposal\x12\x33\n\tinstances\x18\x02 \x03(\x0b\x32\x15.pactus.ConsensusInfoR\tinstances\"Q\n\x17GetTxPoolContentRequest\x12\x36\n\x0cpayload_type\x18\x01 \x01(\x0e\x32\x13.pactus.PayloadTypeR\x0bpayloadType\"E\n\x18GetTxPoolContentResponse\x12)\n\x03txs\x18\x01 \x03(\x0b\x32\x17.pactus.TransactionInfoR\x03txs\"\xdc\x02\n\rValidatorInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x1d\n\npublic_key\x18\x03 \x01(\tR\tpublicKey\x12\x16\n\x06number\x18\x04 \x01(\x05R\x06number\x12\x14\n\x05stake\x18\x05 \x01(\x03R\x05stake\x12.\n\x13last_bonding_height\x18\x06 \x01(\rR\x11lastBondingHeight\x12\x32\n\x15last_sortition_height\x18\x07 \x01(\rR\x13lastSortitionHeight\x12)\n\x10unbonding_height\x18\x08 \x01(\rR\x0funbondingHeight\x12\x18\n\x07\x61\x64\x64ress\x18\t \x01(\tR\x07\x61\x64\x64ress\x12-\n\x12\x61vailability_score\x18\n \x01(\x01R\x11\x61vailabilityScore\"\x81\x01\n\x0b\x41\x63\x63ountInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n\x04\x64\x61ta\x18\x02 \x01(\tR\x04\x64\x61ta\x12\x16\n\x06number\x18\x03 \x01(\x05R\x06number\x12\x18\n\x07\x62\x61lance\x18\x04 \x01(\x03R\x07\x62\x61lance\x12\x18\n\x07\x61\x64\x64ress\x18\x05 \x01(\tR\x07\x61\x64\x64ress\"\xc4\x01\n\x0f\x42lockHeaderInfo\x12\x18\n\x07version\x18\x01 \x01(\x05R\x07version\x12&\n\x0fprev_block_hash\x18\x02 \x01(\tR\rprevBlockHash\x12\x1d\n\nstate_root\x18\x03 \x01(\tR\tstateRoot\x12%\n\x0esortition_seed\x18\x04 \x01(\tR\rsortitionSeed\x12)\n\x10proposer_address\x18\x05 \x01(\tR\x0fproposerAddress\"\x97\x01\n\x0f\x43\x65rtificateInfo\x12\x12\n\x04hash\x18\x01 \x01(\tR\x04hash\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1e\n\ncommitters\x18\x03 \x03(\x05R\ncommitters\x12\x1c\n\tabsentees\x18\x04 \x03(\x05R\tabsentees\x12\x1c\n\tsignature\x18\x05 \x01(\tR\tsignature\"\xb1\x01\n\x08VoteInfo\x12$\n\x04type\x18\x01 \x01(\x0e\x32\x10.pactus.VoteTypeR\x04type\x12\x14\n\x05voter\x18\x02 \x01(\tR\x05voter\x12\x1d\n\nblock_hash\x18\x03 \x01(\tR\tblockHash\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12\x19\n\x08\x63p_round\x18\x05 \x01(\x05R\x07\x63pRound\x12\x19\n\x08\x63p_value\x18\x06 \x01(\x05R\x07\x63pValue\"\x97\x01\n\rConsensusInfo\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\x12\x16\n\x06\x61\x63tive\x18\x02 \x01(\x08R\x06\x61\x63tive\x12\x16\n\x06height\x18\x03 \x01(\rR\x06height\x12\x14\n\x05round\x18\x04 \x01(\x05R\x05round\x12&\n\x05votes\x18\x05 \x03(\x0b\x32\x10.pactus.VoteInfoR\x05votes\"~\n\x08Proposal\x12\x16\n\x06height\x18\x01 \x01(\rR\x06height\x12\x14\n\x05round\x18\x02 \x01(\x05R\x05round\x12\x1d\n\nblock_data\x18\x03 \x01(\tR\tblockData\x12%\n\x0esignature_data\x18\x04 \x01(\tR\rsignatureData*H\n\x0e\x42lockVerbosity\x12\x0e\n\nBLOCK_DATA\x10\x00\x12\x0e\n\nBLOCK_INFO\x10\x01\x12\x16\n\x12\x42LOCK_TRANSACTIONS\x10\x02*\\\n\x08VoteType\x12\x10\n\x0cVOTE_UNKNOWN\x10\x00\x12\x10\n\x0cVOTE_PREPARE\x10\x01\x12\x12\n\x0eVOTE_PRECOMMIT\x10\x02\x12\x18\n\x14VOTE_CHANGE_PROPOSER\x10\x03\x32\x8b\x07\n\nBlockchain\x12=\n\x08GetBlock\x12\x17.pactus.GetBlockRequest\x1a\x18.pactus.GetBlockResponse\x12I\n\x0cGetBlockHash\x12\x1b.pactus.GetBlockHashRequest\x1a\x1c.pactus.GetBlockHashResponse\x12O\n\x0eGetBlockHeight\x12\x1d.pactus.GetBlockHeightRequest\x1a\x1e.pactus.GetBlockHeightResponse\x12X\n\x11GetBlockchainInfo\x12 .pactus.GetBlockchainInfoRequest\x1a!.pactus.GetBlockchainInfoResponse\x12U\n\x10GetConsensusInfo\x12\x1f.pactus.GetConsensusInfoRequest\x1a .pactus.GetConsensusInfoResponse\x12\x43\n\nGetAccount\x12\x19.pactus.GetAccountRequest\x1a\x1a.pactus.GetAccountResponse\x12I\n\x0cGetValidator\x12\x1b.pactus.GetValidatorRequest\x1a\x1c.pactus.GetValidatorResponse\x12Y\n\x14GetValidatorByNumber\x12#.pactus.GetValidatorByNumberRequest\x1a\x1c.pactus.GetValidatorResponse\x12\x64\n\x15GetValidatorAddresses\x12$.pactus.GetValidatorAddressesRequest\x1a%.pactus.GetValidatorAddressesResponse\x12I\n\x0cGetPublicKey\x12\x1b.pactus.GetPublicKeyRequest\x1a\x1c.pactus.GetPublicKeyResponse\x12U\n\x10GetTxPoolContent\x12\x1f.pactus.GetTxPoolContentRequest\x1a .pactus.GetTxPoolContentResponseBE\n\x11pactus.blockchainZ0github.com/pactus-project/pactus/www/grpc/pactusb\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'blockchain_pb2', globals()) diff --git a/www/grpc/gen/python/blockchain_pb2.pyi b/www/grpc/gen/python/blockchain_pb2.pyi index 85a5b127d..27b2a9848 100644 --- a/www/grpc/gen/python/blockchain_pb2.pyi +++ b/www/grpc/gen/python/blockchain_pb2.pyi @@ -162,10 +162,12 @@ class GetConsensusInfoRequest(_message.Message): def __init__(self) -> None: ... class GetConsensusInfoResponse(_message.Message): - __slots__ = ("instances",) + __slots__ = ("proposal", "instances") + PROPOSAL_FIELD_NUMBER: _ClassVar[int] INSTANCES_FIELD_NUMBER: _ClassVar[int] + proposal: Proposal instances: _containers.RepeatedCompositeFieldContainer[ConsensusInfo] - def __init__(self, instances: _Optional[_Iterable[_Union[ConsensusInfo, _Mapping]]] = ...) -> None: ... + def __init__(self, proposal: _Optional[_Union[Proposal, _Mapping]] = ..., instances: _Optional[_Iterable[_Union[ConsensusInfo, _Mapping]]] = ...) -> None: ... class GetTxPoolContentRequest(_message.Message): __slots__ = ("payload_type",) @@ -274,3 +276,15 @@ class ConsensusInfo(_message.Message): round: int votes: _containers.RepeatedCompositeFieldContainer[VoteInfo] def __init__(self, address: _Optional[str] = ..., active: bool = ..., height: _Optional[int] = ..., round: _Optional[int] = ..., votes: _Optional[_Iterable[_Union[VoteInfo, _Mapping]]] = ...) -> None: ... + +class Proposal(_message.Message): + __slots__ = ("height", "round", "block_data", "signature_data") + HEIGHT_FIELD_NUMBER: _ClassVar[int] + ROUND_FIELD_NUMBER: _ClassVar[int] + BLOCK_DATA_FIELD_NUMBER: _ClassVar[int] + SIGNATURE_DATA_FIELD_NUMBER: _ClassVar[int] + height: int + round: int + block_data: str + signature_data: str + def __init__(self, height: _Optional[int] = ..., round: _Optional[int] = ..., block_data: _Optional[str] = ..., signature_data: _Optional[str] = ...) -> None: ... diff --git a/www/grpc/gen/python/wallet_pb2.py b/www/grpc/gen/python/wallet_pb2.py index 5dfe4de4d..2f2b028d4 100644 --- a/www/grpc/gen/python/wallet_pb2.py +++ b/www/grpc/gen/python/wallet_pb2.py @@ -14,7 +14,7 @@ import transaction_pb2 as transaction__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cwallet.proto\x12\x06pactus\x1a\x11transaction.proto\"p\n\x0b\x41\x64\x64ressInfo\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\x12\x1d\n\npublic_key\x18\x02 \x01(\tR\tpublicKey\x12\x14\n\x05label\x18\x03 \x01(\tR\x05label\x12\x12\n\x04path\x18\x04 \x01(\tR\x04path\"\xa5\x01\n\x0bHistoryInfo\x12%\n\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12\x12\n\x04time\x18\x02 \x01(\rR\x04time\x12!\n\x0cpayload_type\x18\x03 \x01(\tR\x0bpayloadType\x12 \n\x0b\x64\x65scription\x18\x04 \x01(\tR\x0b\x64\x65scription\x12\x16\n\x06\x61mount\x18\x05 \x01(\x03R\x06\x61mount\"U\n\x18GetAddressHistoryRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x18\n\x07\x61\x64\x64ress\x18\x02 \x01(\tR\x07\x61\x64\x64ress\"S\n\x19GetAddressHistoryResponse\x12\x36\n\x0chistory_info\x18\x01 \x03(\x0b\x32\x13.pactus.HistoryInfoR\x0bhistoryInfo\"\x85\x01\n\x14GetNewAddressRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x36\n\x0c\x61\x64\x64ress_type\x18\x02 \x01(\x0e\x32\x13.pactus.AddressTypeR\x0b\x61\x64\x64ressType\x12\x14\n\x05label\x18\x03 \x01(\tR\x05label\"p\n\x15GetNewAddressResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x36\n\x0c\x61\x64\x64ress_info\x18\x02 \x01(\x0b\x32\x13.pactus.AddressInfoR\x0b\x61\x64\x64ressInfo\"o\n\x14RestoreWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x1a\n\x08mnemonic\x18\x02 \x01(\tR\x08mnemonic\x12\x1a\n\x08password\x18\x03 \x01(\tR\x08password\"8\n\x15RestoreWalletResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"R\n\x13\x43reateWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x1a\n\x08password\x18\x04 \x01(\tR\x08password\"2\n\x14\x43reateWalletResponse\x12\x1a\n\x08mnemonic\x18\x02 \x01(\tR\x08mnemonic\"4\n\x11LoadWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"5\n\x12LoadWalletResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"6\n\x13UnloadWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"7\n\x14UnloadWalletResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\";\n\x1aGetValidatorAddressRequest\x12\x1d\n\npublic_key\x18\x01 \x01(\tR\tpublicKey\"7\n\x1bGetValidatorAddressResponse\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"\x81\x01\n\x19SignRawTransactionRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\'\n\x0fraw_transaction\x18\x02 \x01(\tR\x0erawTransaction\x12\x1a\n\x08password\x18\x03 \x01(\tR\x08password\"y\n\x1aSignRawTransactionResponse\x12%\n\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12\x34\n\x16signed_raw_transaction\x18\x02 \x01(\tR\x14signedRawTransaction\"9\n\x16GetTotalBalanceRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"_\n\x17GetTotalBalanceResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12#\n\rtotal_balance\x18\x02 \x01(\x03R\x0ctotalBalance\"\x85\x01\n\x12SignMessageRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x1a\n\x08password\x18\x02 \x01(\tR\x08password\x12\x18\n\x07\x61\x64\x64ress\x18\x03 \x01(\tR\x07\x61\x64\x64ress\x12\x18\n\x07message\x18\x04 \x01(\tR\x07message\"3\n\x13SignMessageResponse\x12\x1c\n\tsignature\x18\x01 \x01(\tR\tsignature*b\n\x0b\x41\x64\x64ressType\x12\x19\n\x15\x41\x44\x44RESS_TYPE_TREASURY\x10\x00\x12\x1a\n\x16\x41\x44\x44RESS_TYPE_VALIDATOR\x10\x01\x12\x1c\n\x18\x41\x44\x44RESS_TYPE_BLS_ACCOUNT\x10\x02\x32\xb2\x06\n\x06Wallet\x12I\n\x0c\x43reateWallet\x12\x1b.pactus.CreateWalletRequest\x1a\x1c.pactus.CreateWalletResponse\x12L\n\rRestoreWallet\x12\x1c.pactus.RestoreWalletRequest\x1a\x1d.pactus.RestoreWalletResponse\x12\x43\n\nLoadWallet\x12\x19.pactus.LoadWalletRequest\x1a\x1a.pactus.LoadWalletResponse\x12I\n\x0cUnloadWallet\x12\x1b.pactus.UnloadWalletRequest\x1a\x1c.pactus.UnloadWalletResponse\x12R\n\x0fGetTotalBalance\x12\x1e.pactus.GetTotalBalanceRequest\x1a\x1f.pactus.GetTotalBalanceResponse\x12[\n\x12SignRawTransaction\x12!.pactus.SignRawTransactionRequest\x1a\".pactus.SignRawTransactionResponse\x12^\n\x13GetValidatorAddress\x12\".pactus.GetValidatorAddressRequest\x1a#.pactus.GetValidatorAddressResponse\x12L\n\rGetNewAddress\x12\x1c.pactus.GetNewAddressRequest\x1a\x1d.pactus.GetNewAddressResponse\x12X\n\x11GetAddressHistory\x12 .pactus.GetAddressHistoryRequest\x1a!.pactus.GetAddressHistoryResponse\x12\x46\n\x0bSignMessage\x12\x1a.pactus.SignMessageRequest\x1a\x1b.pactus.SignMessageResponseBA\n\rpactus.walletZ0github.com/pactus-project/pactus/www/grpc/pactusb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cwallet.proto\x12\x06pactus\x1a\x11transaction.proto\"p\n\x0b\x41\x64\x64ressInfo\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\x12\x1d\n\npublic_key\x18\x02 \x01(\tR\tpublicKey\x12\x14\n\x05label\x18\x03 \x01(\tR\x05label\x12\x12\n\x04path\x18\x04 \x01(\tR\x04path\"\xa5\x01\n\x0bHistoryInfo\x12%\n\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12\x12\n\x04time\x18\x02 \x01(\rR\x04time\x12!\n\x0cpayload_type\x18\x03 \x01(\tR\x0bpayloadType\x12 \n\x0b\x64\x65scription\x18\x04 \x01(\tR\x0b\x64\x65scription\x12\x16\n\x06\x61mount\x18\x05 \x01(\x03R\x06\x61mount\"U\n\x18GetAddressHistoryRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x18\n\x07\x61\x64\x64ress\x18\x02 \x01(\tR\x07\x61\x64\x64ress\"S\n\x19GetAddressHistoryResponse\x12\x36\n\x0chistory_info\x18\x01 \x03(\x0b\x32\x13.pactus.HistoryInfoR\x0bhistoryInfo\"\xa1\x01\n\x14GetNewAddressRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x36\n\x0c\x61\x64\x64ress_type\x18\x02 \x01(\x0e\x32\x13.pactus.AddressTypeR\x0b\x61\x64\x64ressType\x12\x14\n\x05label\x18\x03 \x01(\tR\x05label\x12\x1a\n\x08password\x18\x04 \x01(\tR\x08password\"p\n\x15GetNewAddressResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x36\n\x0c\x61\x64\x64ress_info\x18\x02 \x01(\x0b\x32\x13.pactus.AddressInfoR\x0b\x61\x64\x64ressInfo\"o\n\x14RestoreWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x1a\n\x08mnemonic\x18\x02 \x01(\tR\x08mnemonic\x12\x1a\n\x08password\x18\x03 \x01(\tR\x08password\"8\n\x15RestoreWalletResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"R\n\x13\x43reateWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x1a\n\x08password\x18\x04 \x01(\tR\x08password\"2\n\x14\x43reateWalletResponse\x12\x1a\n\x08mnemonic\x18\x02 \x01(\tR\x08mnemonic\"4\n\x11LoadWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"5\n\x12LoadWalletResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"6\n\x13UnloadWalletRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"7\n\x14UnloadWalletResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\";\n\x1aGetValidatorAddressRequest\x12\x1d\n\npublic_key\x18\x01 \x01(\tR\tpublicKey\"7\n\x1bGetValidatorAddressResponse\x12\x18\n\x07\x61\x64\x64ress\x18\x01 \x01(\tR\x07\x61\x64\x64ress\"\x81\x01\n\x19SignRawTransactionRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\'\n\x0fraw_transaction\x18\x02 \x01(\tR\x0erawTransaction\x12\x1a\n\x08password\x18\x03 \x01(\tR\x08password\"y\n\x1aSignRawTransactionResponse\x12%\n\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12\x34\n\x16signed_raw_transaction\x18\x02 \x01(\tR\x14signedRawTransaction\"9\n\x16GetTotalBalanceRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\"_\n\x17GetTotalBalanceResponse\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12#\n\rtotal_balance\x18\x02 \x01(\x03R\x0ctotalBalance\"\x85\x01\n\x12SignMessageRequest\x12\x1f\n\x0bwallet_name\x18\x01 \x01(\tR\nwalletName\x12\x1a\n\x08password\x18\x02 \x01(\tR\x08password\x12\x18\n\x07\x61\x64\x64ress\x18\x03 \x01(\tR\x07\x61\x64\x64ress\x12\x18\n\x07message\x18\x04 \x01(\tR\x07message\"3\n\x13SignMessageResponse\x12\x1c\n\tsignature\x18\x01 \x01(\tR\tsignature*\x84\x01\n\x0b\x41\x64\x64ressType\x12\x19\n\x15\x41\x44\x44RESS_TYPE_TREASURY\x10\x00\x12\x1a\n\x16\x41\x44\x44RESS_TYPE_VALIDATOR\x10\x01\x12\x1c\n\x18\x41\x44\x44RESS_TYPE_BLS_ACCOUNT\x10\x02\x12 \n\x1c\x41\x44\x44RESS_TYPE_ED25519_ACCOUNT\x10\x03\x32\xb2\x06\n\x06Wallet\x12I\n\x0c\x43reateWallet\x12\x1b.pactus.CreateWalletRequest\x1a\x1c.pactus.CreateWalletResponse\x12L\n\rRestoreWallet\x12\x1c.pactus.RestoreWalletRequest\x1a\x1d.pactus.RestoreWalletResponse\x12\x43\n\nLoadWallet\x12\x19.pactus.LoadWalletRequest\x1a\x1a.pactus.LoadWalletResponse\x12I\n\x0cUnloadWallet\x12\x1b.pactus.UnloadWalletRequest\x1a\x1c.pactus.UnloadWalletResponse\x12R\n\x0fGetTotalBalance\x12\x1e.pactus.GetTotalBalanceRequest\x1a\x1f.pactus.GetTotalBalanceResponse\x12[\n\x12SignRawTransaction\x12!.pactus.SignRawTransactionRequest\x1a\".pactus.SignRawTransactionResponse\x12^\n\x13GetValidatorAddress\x12\".pactus.GetValidatorAddressRequest\x1a#.pactus.GetValidatorAddressResponse\x12L\n\rGetNewAddress\x12\x1c.pactus.GetNewAddressRequest\x1a\x1d.pactus.GetNewAddressResponse\x12X\n\x11GetAddressHistory\x12 .pactus.GetAddressHistoryRequest\x1a!.pactus.GetAddressHistoryResponse\x12\x46\n\x0bSignMessage\x12\x1a.pactus.SignMessageRequest\x1a\x1b.pactus.SignMessageResponseBA\n\rpactus.walletZ0github.com/pactus-project/pactus/www/grpc/pactusb\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'wallet_pb2', globals()) @@ -22,8 +22,8 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n\rpactus.walletZ0github.com/pactus-project/pactus/www/grpc/pactus' - _ADDRESSTYPE._serialized_start=1994 - _ADDRESSTYPE._serialized_end=2092 + _ADDRESSTYPE._serialized_start=2023 + _ADDRESSTYPE._serialized_end=2155 _ADDRESSINFO._serialized_start=43 _ADDRESSINFO._serialized_end=155 _HISTORYINFO._serialized_start=158 @@ -33,41 +33,41 @@ _GETADDRESSHISTORYRESPONSE._serialized_start=412 _GETADDRESSHISTORYRESPONSE._serialized_end=495 _GETNEWADDRESSREQUEST._serialized_start=498 - _GETNEWADDRESSREQUEST._serialized_end=631 - _GETNEWADDRESSRESPONSE._serialized_start=633 - _GETNEWADDRESSRESPONSE._serialized_end=745 - _RESTOREWALLETREQUEST._serialized_start=747 - _RESTOREWALLETREQUEST._serialized_end=858 - _RESTOREWALLETRESPONSE._serialized_start=860 - _RESTOREWALLETRESPONSE._serialized_end=916 - _CREATEWALLETREQUEST._serialized_start=918 - _CREATEWALLETREQUEST._serialized_end=1000 - _CREATEWALLETRESPONSE._serialized_start=1002 - _CREATEWALLETRESPONSE._serialized_end=1052 - _LOADWALLETREQUEST._serialized_start=1054 - _LOADWALLETREQUEST._serialized_end=1106 - _LOADWALLETRESPONSE._serialized_start=1108 - _LOADWALLETRESPONSE._serialized_end=1161 - _UNLOADWALLETREQUEST._serialized_start=1163 - _UNLOADWALLETREQUEST._serialized_end=1217 - _UNLOADWALLETRESPONSE._serialized_start=1219 - _UNLOADWALLETRESPONSE._serialized_end=1274 - _GETVALIDATORADDRESSREQUEST._serialized_start=1276 - _GETVALIDATORADDRESSREQUEST._serialized_end=1335 - _GETVALIDATORADDRESSRESPONSE._serialized_start=1337 - _GETVALIDATORADDRESSRESPONSE._serialized_end=1392 - _SIGNRAWTRANSACTIONREQUEST._serialized_start=1395 - _SIGNRAWTRANSACTIONREQUEST._serialized_end=1524 - _SIGNRAWTRANSACTIONRESPONSE._serialized_start=1526 - _SIGNRAWTRANSACTIONRESPONSE._serialized_end=1647 - _GETTOTALBALANCEREQUEST._serialized_start=1649 - _GETTOTALBALANCEREQUEST._serialized_end=1706 - _GETTOTALBALANCERESPONSE._serialized_start=1708 - _GETTOTALBALANCERESPONSE._serialized_end=1803 - _SIGNMESSAGEREQUEST._serialized_start=1806 - _SIGNMESSAGEREQUEST._serialized_end=1939 - _SIGNMESSAGERESPONSE._serialized_start=1941 - _SIGNMESSAGERESPONSE._serialized_end=1992 - _WALLET._serialized_start=2095 - _WALLET._serialized_end=2913 + _GETNEWADDRESSREQUEST._serialized_end=659 + _GETNEWADDRESSRESPONSE._serialized_start=661 + _GETNEWADDRESSRESPONSE._serialized_end=773 + _RESTOREWALLETREQUEST._serialized_start=775 + _RESTOREWALLETREQUEST._serialized_end=886 + _RESTOREWALLETRESPONSE._serialized_start=888 + _RESTOREWALLETRESPONSE._serialized_end=944 + _CREATEWALLETREQUEST._serialized_start=946 + _CREATEWALLETREQUEST._serialized_end=1028 + _CREATEWALLETRESPONSE._serialized_start=1030 + _CREATEWALLETRESPONSE._serialized_end=1080 + _LOADWALLETREQUEST._serialized_start=1082 + _LOADWALLETREQUEST._serialized_end=1134 + _LOADWALLETRESPONSE._serialized_start=1136 + _LOADWALLETRESPONSE._serialized_end=1189 + _UNLOADWALLETREQUEST._serialized_start=1191 + _UNLOADWALLETREQUEST._serialized_end=1245 + _UNLOADWALLETRESPONSE._serialized_start=1247 + _UNLOADWALLETRESPONSE._serialized_end=1302 + _GETVALIDATORADDRESSREQUEST._serialized_start=1304 + _GETVALIDATORADDRESSREQUEST._serialized_end=1363 + _GETVALIDATORADDRESSRESPONSE._serialized_start=1365 + _GETVALIDATORADDRESSRESPONSE._serialized_end=1420 + _SIGNRAWTRANSACTIONREQUEST._serialized_start=1423 + _SIGNRAWTRANSACTIONREQUEST._serialized_end=1552 + _SIGNRAWTRANSACTIONRESPONSE._serialized_start=1554 + _SIGNRAWTRANSACTIONRESPONSE._serialized_end=1675 + _GETTOTALBALANCEREQUEST._serialized_start=1677 + _GETTOTALBALANCEREQUEST._serialized_end=1734 + _GETTOTALBALANCERESPONSE._serialized_start=1736 + _GETTOTALBALANCERESPONSE._serialized_end=1831 + _SIGNMESSAGEREQUEST._serialized_start=1834 + _SIGNMESSAGEREQUEST._serialized_end=1967 + _SIGNMESSAGERESPONSE._serialized_start=1969 + _SIGNMESSAGERESPONSE._serialized_end=2020 + _WALLET._serialized_start=2158 + _WALLET._serialized_end=2976 # @@protoc_insertion_point(module_scope) diff --git a/www/grpc/gen/python/wallet_pb2.pyi b/www/grpc/gen/python/wallet_pb2.pyi index 023fad277..7cb1ab386 100644 --- a/www/grpc/gen/python/wallet_pb2.pyi +++ b/www/grpc/gen/python/wallet_pb2.pyi @@ -12,9 +12,11 @@ class AddressType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): ADDRESS_TYPE_TREASURY: _ClassVar[AddressType] ADDRESS_TYPE_VALIDATOR: _ClassVar[AddressType] ADDRESS_TYPE_BLS_ACCOUNT: _ClassVar[AddressType] + ADDRESS_TYPE_ED25519_ACCOUNT: _ClassVar[AddressType] ADDRESS_TYPE_TREASURY: AddressType ADDRESS_TYPE_VALIDATOR: AddressType ADDRESS_TYPE_BLS_ACCOUNT: AddressType +ADDRESS_TYPE_ED25519_ACCOUNT: AddressType class AddressInfo(_message.Message): __slots__ = ("address", "public_key", "label", "path") @@ -57,14 +59,16 @@ class GetAddressHistoryResponse(_message.Message): def __init__(self, history_info: _Optional[_Iterable[_Union[HistoryInfo, _Mapping]]] = ...) -> None: ... class GetNewAddressRequest(_message.Message): - __slots__ = ("wallet_name", "address_type", "label") + __slots__ = ("wallet_name", "address_type", "label", "password") WALLET_NAME_FIELD_NUMBER: _ClassVar[int] ADDRESS_TYPE_FIELD_NUMBER: _ClassVar[int] LABEL_FIELD_NUMBER: _ClassVar[int] + PASSWORD_FIELD_NUMBER: _ClassVar[int] wallet_name: str address_type: AddressType label: str - def __init__(self, wallet_name: _Optional[str] = ..., address_type: _Optional[_Union[AddressType, str]] = ..., label: _Optional[str] = ...) -> None: ... + password: str + def __init__(self, wallet_name: _Optional[str] = ..., address_type: _Optional[_Union[AddressType, str]] = ..., label: _Optional[str] = ..., password: _Optional[str] = ...) -> None: ... class GetNewAddressResponse(_message.Message): __slots__ = ("wallet_name", "address_info") diff --git a/www/grpc/gen/rust/pactus.rs b/www/grpc/gen/rust/pactus.rs index d9b89a303..f5f5e27b2 100644 --- a/www/grpc/gen/rust/pactus.rs +++ b/www/grpc/gen/rust/pactus.rs @@ -545,12 +545,12 @@ pub struct GetConsensusInfoRequest { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetConsensusInfoResponse { - /// List of consensus instances. - #[prost(message, repeated, tag="1")] - pub instances: ::prost::alloc::vec::Vec, /// The proposal of the consensus info. - #[prost(message, optional, tag="6")] + #[prost(message, optional, tag="1")] pub proposal: ::core::option::Option, + /// List of consensus instances. + #[prost(message, repeated, tag="2")] + pub instances: ::prost::alloc::vec::Vec, } /// Request message to retrieve transactions in the transaction pool. #[allow(clippy::derive_partial_eq_without_eq)] @@ -1062,6 +1062,9 @@ pub struct GetNewAddressRequest { /// A label for the new address. #[prost(string, tag="3")] pub label: ::prost::alloc::string::String, + /// Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT. + #[prost(string, tag="4")] + pub password: ::prost::alloc::string::String, } /// Response message containing the newly generated address. #[allow(clippy::derive_partial_eq_without_eq)] @@ -1245,6 +1248,9 @@ pub enum AddressType { Validator = 1, /// Account address type with BLS signature scheme. BlsAccount = 2, + /// Account address type with Ed25519 signature scheme. + /// Note: Generating a new Ed25519 address requires the wallet password. + Ed25519Account = 3, } impl AddressType { /// String value of the enum field names used in the ProtoBuf definition. @@ -1256,6 +1262,7 @@ impl AddressType { AddressType::Treasury => "ADDRESS_TYPE_TREASURY", AddressType::Validator => "ADDRESS_TYPE_VALIDATOR", AddressType::BlsAccount => "ADDRESS_TYPE_BLS_ACCOUNT", + AddressType::Ed25519Account => "ADDRESS_TYPE_ED25519_ACCOUNT", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -1264,6 +1271,7 @@ impl AddressType { "ADDRESS_TYPE_TREASURY" => Some(Self::Treasury), "ADDRESS_TYPE_VALIDATOR" => Some(Self::Validator), "ADDRESS_TYPE_BLS_ACCOUNT" => Some(Self::BlsAccount), + "ADDRESS_TYPE_ED25519_ACCOUNT" => Some(Self::Ed25519Account), _ => None, } } diff --git a/www/grpc/gen/rust/pactus.serde.rs b/www/grpc/gen/rust/pactus.serde.rs index c62bf4ab1..c6ab16ca7 100644 --- a/www/grpc/gen/rust/pactus.serde.rs +++ b/www/grpc/gen/rust/pactus.serde.rs @@ -315,6 +315,7 @@ impl serde::Serialize for AddressType { Self::Treasury => "ADDRESS_TYPE_TREASURY", Self::Validator => "ADDRESS_TYPE_VALIDATOR", Self::BlsAccount => "ADDRESS_TYPE_BLS_ACCOUNT", + Self::Ed25519Account => "ADDRESS_TYPE_ED25519_ACCOUNT", }; serializer.serialize_str(variant) } @@ -329,6 +330,7 @@ impl<'de> serde::Deserialize<'de> for AddressType { "ADDRESS_TYPE_TREASURY", "ADDRESS_TYPE_VALIDATOR", "ADDRESS_TYPE_BLS_ACCOUNT", + "ADDRESS_TYPE_ED25519_ACCOUNT", ]; struct GeneratedVisitor; @@ -374,6 +376,7 @@ impl<'de> serde::Deserialize<'de> for AddressType { "ADDRESS_TYPE_TREASURY" => Ok(AddressType::Treasury), "ADDRESS_TYPE_VALIDATOR" => Ok(AddressType::Validator), "ADDRESS_TYPE_BLS_ACCOUNT" => Ok(AddressType::BlsAccount), + "ADDRESS_TYPE_ED25519_ACCOUNT" => Ok(AddressType::Ed25519Account), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } } @@ -3191,19 +3194,19 @@ impl serde::Serialize for GetConsensusInfoResponse { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.instances.is_empty() { - len += 1; - } if self.proposal.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("pactus.GetConsensusInfoResponse", len)?; if !self.instances.is_empty() { - struct_ser.serialize_field("instances", &self.instances)?; + len += 1; } + let mut struct_ser = serializer.serialize_struct("pactus.GetConsensusInfoResponse", len)?; if let Some(v) = self.proposal.as_ref() { struct_ser.serialize_field("proposal", v)?; } + if !self.instances.is_empty() { + struct_ser.serialize_field("instances", &self.instances)?; + } struct_ser.end() } } @@ -3214,14 +3217,14 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "instances", "proposal", + "instances", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Instances, Proposal, + Instances, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -3243,8 +3246,8 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { E: serde::de::Error, { match value { - "instances" => Ok(GeneratedField::Instances), "proposal" => Ok(GeneratedField::Proposal), + "instances" => Ok(GeneratedField::Instances), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -3264,27 +3267,27 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { where V: serde::de::MapAccess<'de>, { - let mut instances__ = None; let mut proposal__ = None; + let mut instances__ = None; while let Some(k) = map.next_key()? { match k { - GeneratedField::Instances => { - if instances__.is_some() { - return Err(serde::de::Error::duplicate_field("instances")); - } - instances__ = Some(map.next_value()?); - } GeneratedField::Proposal => { if proposal__.is_some() { return Err(serde::de::Error::duplicate_field("proposal")); } proposal__ = map.next_value()?; } + GeneratedField::Instances => { + if instances__.is_some() { + return Err(serde::de::Error::duplicate_field("instances")); + } + instances__ = Some(map.next_value()?); + } } } Ok(GetConsensusInfoResponse { - instances: instances__.unwrap_or_default(), proposal: proposal__, + instances: instances__.unwrap_or_default(), }) } } @@ -3616,6 +3619,9 @@ impl serde::Serialize for GetNewAddressRequest { if !self.label.is_empty() { len += 1; } + if !self.password.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("pactus.GetNewAddressRequest", len)?; if !self.wallet_name.is_empty() { struct_ser.serialize_field("walletName", &self.wallet_name)?; @@ -3628,6 +3634,9 @@ impl serde::Serialize for GetNewAddressRequest { if !self.label.is_empty() { struct_ser.serialize_field("label", &self.label)?; } + if !self.password.is_empty() { + struct_ser.serialize_field("password", &self.password)?; + } struct_ser.end() } } @@ -3643,6 +3652,7 @@ impl<'de> serde::Deserialize<'de> for GetNewAddressRequest { "address_type", "addressType", "label", + "password", ]; #[allow(clippy::enum_variant_names)] @@ -3650,6 +3660,7 @@ impl<'de> serde::Deserialize<'de> for GetNewAddressRequest { WalletName, AddressType, Label, + Password, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -3674,6 +3685,7 @@ impl<'de> serde::Deserialize<'de> for GetNewAddressRequest { "walletName" | "wallet_name" => Ok(GeneratedField::WalletName), "addressType" | "address_type" => Ok(GeneratedField::AddressType), "label" => Ok(GeneratedField::Label), + "password" => Ok(GeneratedField::Password), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -3696,6 +3708,7 @@ impl<'de> serde::Deserialize<'de> for GetNewAddressRequest { let mut wallet_name__ = None; let mut address_type__ = None; let mut label__ = None; + let mut password__ = None; while let Some(k) = map.next_key()? { match k { GeneratedField::WalletName => { @@ -3716,12 +3729,19 @@ impl<'de> serde::Deserialize<'de> for GetNewAddressRequest { } label__ = Some(map.next_value()?); } + GeneratedField::Password => { + if password__.is_some() { + return Err(serde::de::Error::duplicate_field("password")); + } + password__ = Some(map.next_value()?); + } } } Ok(GetNewAddressRequest { wallet_name: wallet_name__.unwrap_or_default(), address_type: address_type__.unwrap_or_default(), label: label__.unwrap_or_default(), + password: password__.unwrap_or_default(), }) } } diff --git a/www/grpc/proto/wallet.proto b/www/grpc/proto/wallet.proto index 9deaa99bb..8b8c7d88a 100644 --- a/www/grpc/proto/wallet.proto +++ b/www/grpc/proto/wallet.proto @@ -55,6 +55,9 @@ enum AddressType { ADDRESS_TYPE_VALIDATOR = 1; // Account address type with BLS signature scheme. ADDRESS_TYPE_BLS_ACCOUNT = 2; + // Account address type with Ed25519 signature scheme. + // Note: Generating a new Ed25519 address requires the wallet password. + ADDRESS_TYPE_ED25519_ACCOUNT = 3; } // Message containing address information. @@ -105,6 +108,8 @@ message GetNewAddressRequest { AddressType address_type = 2; // A label for the new address. string label = 3; + // Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT. + string password = 4; } // Response message containing the newly generated address. diff --git a/www/grpc/swagger-ui/pactus.swagger.json b/www/grpc/swagger-ui/pactus.swagger.json index 293fcad78..ef57177be 100644 --- a/www/grpc/swagger-ui/pactus.swagger.json +++ b/www/grpc/swagger-ui/pactus.swagger.json @@ -971,14 +971,15 @@ }, { "name": "addressType", - "description": "The type of address to generate.\n\n - ADDRESS_TYPE_TREASURY: Treasury address type.\nShould not be used to generate new addresses.\n - ADDRESS_TYPE_VALIDATOR: Validator address type.\n - ADDRESS_TYPE_BLS_ACCOUNT: Account address type with BLS signature scheme.", + "description": "The type of address to generate.\n\n - ADDRESS_TYPE_TREASURY: Treasury address type.\nShould not be used to generate new addresses.\n - ADDRESS_TYPE_VALIDATOR: Validator address type.\n - ADDRESS_TYPE_BLS_ACCOUNT: Account address type with BLS signature scheme.\n - ADDRESS_TYPE_ED25519_ACCOUNT: Account address type with Ed25519 signature scheme.\nNote: Generating a new Ed25519 address requires the wallet password.", "in": "query", "required": false, "type": "string", "enum": [ "ADDRESS_TYPE_TREASURY", "ADDRESS_TYPE_VALIDATOR", - "ADDRESS_TYPE_BLS_ACCOUNT" + "ADDRESS_TYPE_BLS_ACCOUNT", + "ADDRESS_TYPE_ED25519_ACCOUNT" ], "default": "ADDRESS_TYPE_TREASURY" }, @@ -988,6 +989,13 @@ "in": "query", "required": false, "type": "string" + }, + { + "name": "password", + "description": "Password for the new address. It's required when address_type is ADDRESS_TYPE_ED25519_ACCOUNT.", + "in": "query", + "required": false, + "type": "string" } ], "tags": [ @@ -1325,10 +1333,11 @@ "enum": [ "ADDRESS_TYPE_TREASURY", "ADDRESS_TYPE_VALIDATOR", - "ADDRESS_TYPE_BLS_ACCOUNT" + "ADDRESS_TYPE_BLS_ACCOUNT", + "ADDRESS_TYPE_ED25519_ACCOUNT" ], "default": "ADDRESS_TYPE_TREASURY", - "description": "Enum for the address type.\n\n - ADDRESS_TYPE_TREASURY: Treasury address type.\nShould not be used to generate new addresses.\n - ADDRESS_TYPE_VALIDATOR: Validator address type.\n - ADDRESS_TYPE_BLS_ACCOUNT: Account address type with BLS signature scheme." + "description": "Enum for the address type.\n\n - ADDRESS_TYPE_TREASURY: Treasury address type.\nShould not be used to generate new addresses.\n - ADDRESS_TYPE_VALIDATOR: Validator address type.\n - ADDRESS_TYPE_BLS_ACCOUNT: Account address type with BLS signature scheme.\n - ADDRESS_TYPE_ED25519_ACCOUNT: Account address type with Ed25519 signature scheme.\nNote: Generating a new Ed25519 address requires the wallet password." }, "pactusBlockHeaderInfo": { "type": "object", @@ -1636,6 +1645,10 @@ "pactusGetConsensusInfoResponse": { "type": "object", "properties": { + "proposal": { + "$ref": "#/definitions/pactusProposal", + "description": "The proposal of the consensus info." + }, "instances": { "type": "array", "items": { @@ -1643,10 +1656,6 @@ "$ref": "#/definitions/pactusConsensusInfo" }, "description": "List of consensus instances." - }, - "proposal": { - "$ref": "#/definitions/pactusProposal", - "description": "The proposal of the consensus info." } }, "description": "Message containing the response with consensus information." diff --git a/www/grpc/wallet.go b/www/grpc/wallet.go index 1c32744a1..b9f018bd4 100644 --- a/www/grpc/wallet.go +++ b/www/grpc/wallet.go @@ -158,6 +158,7 @@ func (s *walletServer) GetNewAddress(_ context.Context, data, err := s.walletManager.GetNewAddress( req.WalletName, req.Label, + req.Password, crypto.AddressType(req.AddressType), ) if err != nil { From 1dc4092921f8a39d4453cec95bf2e7676671fb7c Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Wed, 4 Sep 2024 06:20:13 +0330 Subject: [PATCH 22/25] feat(gtk): support create Ed25519 in gtk (#1489) --- cmd/gtk/dialog_wallet_create_address.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/cmd/gtk/dialog_wallet_create_address.go b/cmd/gtk/dialog_wallet_create_address.go index 399837d57..4a5bac9da 100644 --- a/cmd/gtk/dialog_wallet_create_address.go +++ b/cmd/gtk/dialog_wallet_create_address.go @@ -4,7 +4,6 @@ package main import ( _ "embed" - "fmt" "github.com/gotk3/gotk3/gtk" "github.com/pactus-project/pactus/wallet" @@ -21,7 +20,8 @@ func createAddress(ww *widgetWallet) { addressLabel := getEntryObj(builder, "id_entry_account_label") addressTypeCombo := getComboBoxTextObj(builder, "id_combo_address_type") - addressTypeCombo.Append(wallet.AddressTypeBLSAccount, "Account") + addressTypeCombo.Append(wallet.AddressTypeEd25519Account, "ED25519 Account") + addressTypeCombo.Append(wallet.AddressTypeBLSAccount, "BLS Account") addressTypeCombo.Append(wallet.AddressTypeValidator, "Validator") addressTypeCombo.SetActive(0) @@ -36,12 +36,18 @@ func createAddress(ww *widgetWallet) { walletAddressType := addressTypeCombo.GetActiveID() fatalErrorCheck(err) - if walletAddressType == wallet.AddressTypeBLSAccount { + switch walletAddressType { + case wallet.AddressTypeEd25519Account: + password, ok := getWalletPassword(ww.model.wallet) + if !ok { + return + } + + _, err = ww.model.wallet.NewEd25519AccountAddress(walletAddressLabel, password) + case wallet.AddressTypeBLSAccount: _, err = ww.model.wallet.NewBLSAccountAddress(walletAddressLabel) - } else if walletAddressType == wallet.AddressTypeValidator { + case wallet.AddressTypeValidator: _, err = ww.model.wallet.NewValidatorAddress(walletAddressLabel) - } else { - err = fmt.Errorf("invalid address type '%s'", walletAddressType) } errorCheck(err) From 1c6ddfed9c5ba6fdc24e2d08229c4bbe5408577f Mon Sep 17 00:00:00 2001 From: b00f Date: Wed, 4 Sep 2024 13:28:52 +0800 Subject: [PATCH 23/25] feat(state): enable Ed25519 for the Testnet (#1497) --- genesis/genesis.go | 4 ++++ genesis/genesis_test.go | 40 +++++++++++++++++++++------------------- state/execution.go | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/genesis/genesis.go b/genesis/genesis.go index 9890d30a8..8e5c55fce 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -27,6 +27,10 @@ func (n ChainType) IsMainnet() bool { return n == Mainnet } +func (n ChainType) IsTestnet() bool { + return n == Testnet +} + func (n ChainType) String() string { switch n { case Mainnet: diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go index 0b8bedcff..b9a955cbc 100644 --- a/genesis/genesis_test.go +++ b/genesis/genesis_test.go @@ -47,25 +47,6 @@ func TestMarshaling(t *testing.T) { assert.Error(t, err, "file not found") } -func TestGenesisTestnet(t *testing.T) { - crypto.AddressHRP = "tpc" - - gen := genesis.TestnetGenesis() - assert.Equal(t, 4, len(gen.Validators())) - assert.Equal(t, 5, len(gen.Accounts())) - - genTime, _ := time.Parse("2006-01-02", "2024-03-16") - expected, _ := hash.FromString("13f96e6fbc9e0de0d53537ac5e894fc8e66be1600436db2df1511dc30696e822") - assert.Equal(t, expected, gen.Hash()) - assert.Equal(t, genTime, gen.GenesisTime()) - assert.Equal(t, uint32(360), gen.Params().BondInterval) - assert.Equal(t, genesis.Testnet, gen.ChainType()) - assert.Equal(t, amount.Amount(42e15), gen.TotalSupply()) - - // reset address HRP global variable to miannet to prevent next tests failing. - crypto.AddressHRP = "pc" -} - func TestGenesisMainnet(t *testing.T) { gen := genesis.MainnetGenesis() assert.Equal(t, len(gen.Validators()), 4) @@ -79,6 +60,7 @@ func TestGenesisMainnet(t *testing.T) { assert.Equal(t, uint32(8640*21), gen.Params().UnbondInterval) assert.Equal(t, genesis.Mainnet, gen.ChainType()) assert.Equal(t, amount.Amount(42e15), gen.TotalSupply()) + assert.True(t, gen.ChainType().IsMainnet()) } func TestCheckGenesisAccountAndValidator(t *testing.T) { @@ -104,3 +86,23 @@ func TestCheckGenesisAccountAndValidator(t *testing.T) { assert.Equal(t, vals[i].Hash(), val.Hash()) } } + +func TestGenesisTestnet(t *testing.T) { + crypto.AddressHRP = "tpc" + + gen := genesis.TestnetGenesis() + assert.Equal(t, 4, len(gen.Validators())) + assert.Equal(t, 5, len(gen.Accounts())) + + genTime, _ := time.Parse("2006-01-02", "2024-03-16") + expected, _ := hash.FromString("13f96e6fbc9e0de0d53537ac5e894fc8e66be1600436db2df1511dc30696e822") + assert.Equal(t, expected, gen.Hash()) + assert.Equal(t, genTime, gen.GenesisTime()) + assert.Equal(t, uint32(360), gen.Params().BondInterval) + assert.Equal(t, genesis.Testnet, gen.ChainType()) + assert.Equal(t, amount.Amount(42e15), gen.TotalSupply()) + assert.True(t, gen.ChainType().IsTestnet()) + + // reset address HRP global variable to miannet to prevent next tests failing. + crypto.AddressHRP = "pc" +} diff --git a/state/execution.go b/state/execution.go index e97942e69..6199af4fc 100644 --- a/state/execution.go +++ b/state/execution.go @@ -26,6 +26,10 @@ func (st *state) executeBlock(b *block.Block, sb sandbox.Sandbox, check bool) er } if check { + if err := st.checkEd25519Fork(trx); err != nil { + return err + } + err := execution.CheckAndExecute(trx, sb, true) if err != nil { return err @@ -52,3 +56,22 @@ func (st *state) executeBlock(b *block.Block, sb sandbox.Sandbox, check bool) er return nil } + +func (st *state) checkEd25519Fork(trx *tx.Tx) error { + // TODO: remove me after enabling Ed255519 + if trx.Payload().Signer().Type() == crypto.AddressTypeEd25519Account { + if st.genDoc.ChainType().IsMainnet() { + return errors.Errorf(errors.ErrInvalidTx, + "ed255519 not supported yet") + } + + if st.genDoc.ChainType().IsTestnet() { + if st.lastInfo.BlockHeight() < 1_320_000 { + return errors.Errorf(errors.ErrInvalidTx, + "ed255519 not supported yet") + } + } + } + + return nil +} From fe806c9ecf6ecfaa8ce77d664110c11948ee5ec0 Mon Sep 17 00:00:00 2001 From: Javad Rajabzadeh Date: Tue, 10 Sep 2024 14:09:05 +0330 Subject: [PATCH 24/25] fix(wallet): add memo in confirmation wallet CLI (#1499) --- cmd/wallet/tx.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/wallet/tx.go b/cmd/wallet/tx.go index 17b37fe69..ea8a428f1 100644 --- a/cmd/wallet/tx.go +++ b/cmd/wallet/tx.go @@ -61,6 +61,7 @@ func buildTransferTxCmd(parentCmd *cobra.Command) { cmd.PrintInfoMsgf("To : %s", to) cmd.PrintInfoMsgf("Amount: %s", amt) cmd.PrintInfoMsgf("Fee : %s", trx.Fee()) + cmd.PrintInfoMsgf("Memo : %s", trx.Memo()) signAndPublishTx(wlt, trx, *noConfirmOpt, *passOpt) } @@ -106,6 +107,7 @@ func buildBondTxCmd(parentCmd *cobra.Command) { cmd.PrintInfoMsgf("Validator: %s", to) cmd.PrintInfoMsgf("Stake : %s", amt) cmd.PrintInfoMsgf("Fee : %s", trx.Fee()) + cmd.PrintInfoMsgf("Memo : %s", trx.Memo()) signAndPublishTx(wlt, trx, *noConfirmOpt, *passOpt) } @@ -145,6 +147,7 @@ func buildUnbondTxCmd(parentCmd *cobra.Command) { cmd.PrintInfoMsgf("You are going to sign this \033[1mUnbond\033[0m transition:") cmd.PrintInfoMsgf("Validator: %s", from) cmd.PrintInfoMsgf("Fee : %s", trx.Fee()) + cmd.PrintInfoMsgf("Memo : %s", trx.Memo()) signAndPublishTx(wlt, trx, *noConfirmOpt, *passOpt) } @@ -189,6 +192,7 @@ func buildWithdrawTxCmd(parentCmd *cobra.Command) { cmd.PrintInfoMsgf("Account : %s", to) cmd.PrintInfoMsgf("Amount : %s", amt) cmd.PrintInfoMsgf("Fee : %s", trx.Fee()) + cmd.PrintInfoMsgf("Memo : %s", trx.Memo()) signAndPublishTx(wlt, trx, *noConfirmOpt, *passOpt) } From 9eeb498383ed5bb674483b964ba716c6a2986524 Mon Sep 17 00:00:00 2001 From: Maxi Date: Tue, 10 Sep 2024 11:46:33 +0100 Subject: [PATCH 25/25] feat(cmd): pactus-wallet add info commands (#1496) --- cmd/wallet/history.go | 2 +- cmd/wallet/info.go | 28 ++++++++++++++++++++++++++++ cmd/wallet/main.go | 1 + wallet/history_test.go | 4 ++-- wallet/manager.go | 2 +- wallet/wallet.go | 14 +++++++++++++- 6 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 cmd/wallet/info.go diff --git a/cmd/wallet/history.go b/cmd/wallet/history.go index 96115940a..4fd8306c7 100644 --- a/cmd/wallet/history.go +++ b/cmd/wallet/history.go @@ -63,7 +63,7 @@ func buildShowHistoryCmd(parentCmd *cobra.Command) { wlt, err := openWallet() cmd.FatalErrorCheck(err) - history := wlt.GetHistory(addr) + history := wlt.History(addr) for i, h := range history { if h.Time != nil { cmd.PrintInfoMsgf("%d %v %v %v %s\t%v", diff --git a/cmd/wallet/info.go b/cmd/wallet/info.go new file mode 100644 index 000000000..1a659396d --- /dev/null +++ b/cmd/wallet/info.go @@ -0,0 +1,28 @@ +package main + +import ( + "time" + + "github.com/pactus-project/pactus/cmd" + "github.com/spf13/cobra" +) + +// buildInfoCmd builds all sub-commands related to the wallet information. +func buildInfoCmd(parentCmd *cobra.Command) { + infoCmd := &cobra.Command{ + Use: "info", + Short: "retrieving the wallet information.", + } + + parentCmd.AddCommand(infoCmd) + + infoCmd.Run = func(_ *cobra.Command, _ []string) { + wlt, err := openWallet() + cmd.FatalErrorCheck(err) + + cmd.PrintInfoMsgf("version: %d", wlt.Version()) + cmd.PrintInfoMsgf("created at: %s", wlt.CreationTime().Format(time.RFC3339)) + cmd.PrintInfoMsgf("is encrtypted: %t", wlt.IsEncrypted()) + cmd.PrintInfoMsgf("network: %s", wlt.Network().String()) + } +} diff --git a/cmd/wallet/main.go b/cmd/wallet/main.go index 6da00a9fe..9187e4132 100644 --- a/cmd/wallet/main.go +++ b/cmd/wallet/main.go @@ -63,6 +63,7 @@ func main() { buildAllTransactionCmd(rootCmd) buildAllAddrCmd(rootCmd) buildAllHistoryCmd(rootCmd) + buildInfoCmd(rootCmd) err := rootCmd.Execute() if err != nil { diff --git a/wallet/history_test.go b/wallet/history_test.go index b82ec334d..c314cb01d 100644 --- a/wallet/history_test.go +++ b/wallet/history_test.go @@ -10,7 +10,7 @@ func TestGetHistory(t *testing.T) { td := setup(t) defer td.Close() - history := td.wallet.GetHistory(td.RandAccAddress().String()) + history := td.wallet.History(td.RandAccAddress().String()) assert.Empty(t, history) } @@ -23,6 +23,6 @@ func TestAddDuplicatedTrx(t *testing.T) { assert.NoError(t, err) assert.Equal(t, trx.ID().String(), id) - history := td.wallet.GetHistory(trx.Payload().Signer().String()) + history := td.wallet.History(trx.Payload().Signer().String()) assert.Equal(t, id, history[0].TxID) } diff --git a/wallet/manager.go b/wallet/manager.go index 2361d9ff8..37d2c4b79 100644 --- a/wallet/manager.go +++ b/wallet/manager.go @@ -200,7 +200,7 @@ func (wm *Manager) AddressHistory( return nil, status.Errorf(codes.NotFound, "wallet is not loaded") } - return wlt.GetHistory(address), nil + return wlt.History(address), nil } func (wm *Manager) SignMessage(walletName, password, addr, msg string) (string, error) { diff --git a/wallet/wallet.go b/wallet/wallet.go index 0f27792be..bafa18e9a 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -490,7 +490,7 @@ func (w *Wallet) AddTransaction(id tx.ID) error { return nil } -func (w *Wallet) GetHistory(addr string) []HistoryInfo { +func (w *Wallet) History(addr string) []HistoryInfo { return w.store.History.getAddrHistory(addr) } @@ -502,3 +502,15 @@ func (w *Wallet) SignMessage(password, addr, msg string) (string, error) { return prv.Sign([]byte(msg)).String(), nil } + +func (w *Wallet) Version() int { + return w.store.Version +} + +func (w *Wallet) CreationTime() time.Time { + return w.store.CreatedAt +} + +func (w *Wallet) Network() genesis.ChainType { + return w.store.Network +}