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/Makefile b/Makefile index 28d1f8642..42dbd216b 100644 --- a/Makefile +++ b/Makefile @@ -20,12 +20,11 @@ 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 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/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/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.") 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/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) 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) 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, diff --git a/cmd/shell/main.go b/cmd/shell/main.go index 7bf5352ff..e5461ea94 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,23 +21,58 @@ const ( defaultResponseFormat = "prettyjson" ) +var _prefix string + func main() { var ( - username string - password string + serverAddr string + username string + password string ) 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, + 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 +83,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) + cmd.PrintErrorMsgf(err.Error()) + } +} + +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/cmd/wallet/address.go b/cmd/wallet/address.go index 170813350..fe5058620 100644 --- a/cmd/wallet/address.go +++ b/cmd/wallet/address.go @@ -86,6 +86,12 @@ func buildNewAddressCmd(parentCmd *cobra.Command) { if *addressType == wallet.AddressTypeBLSAccount { addressInfo, err = wlt.NewBLSAccountAddress(label) + } else if *addressType == wallet.AddressTypeEd25519Account { + password := "" + if wlt.IsEncrypted() { + password = cmd.PromptInput("Password") + } + addressInfo, err = wlt.NewEd25519AccountAddress(label, password) } else if *addressType == wallet.AddressTypeValidator { addressInfo, err = wlt.NewValidatorAddress(label) } else { @@ -201,7 +207,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/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/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) } 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/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/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/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/crypto/address.go b/crypto/address.go index 1cea11dfb..09b1bb356 100644 --- a/crypto/address.go +++ b/crypto/address.go @@ -14,13 +14,15 @@ 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 ( - SignatureTypeBLS byte = 1 + SignatureTypeBLS byte = 1 + SignatureTypeEd25519 byte = 3 ) const ( @@ -51,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) } @@ -110,7 +116,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) @@ -126,7 +133,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) @@ -139,7 +147,8 @@ func (addr Address) SerializeSize() int { case AddressTypeTreasury: return 1 case AddressTypeValidator, - AddressTypeBLSAccount: + AddressTypeBLSAccount, + AddressTypeEd25519Account: return AddressSize default: return 0 @@ -152,7 +161,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 cdb835566..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, }, { - "pc1r0hrct7eflrpw4ccrttxzs4qud2axex4dwc9mn4", - crypto.InvalidAddressTypeError(3), + "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) } @@ -137,13 +172,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, @@ -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/crypto/bls/bls_test.go b/crypto/bls/bls_test.go index 9fd940103..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) @@ -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() 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..741f1e25c 100644 --- a/crypto/bls/private_key.go +++ b/crypto/bls/private_key.go @@ -160,6 +160,11 @@ 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 { + 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 722ac3a87..9d6aa40ac 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,13 @@ 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 { + 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 1ceccfe66..43cae9f70 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,13 @@ 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 { + 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.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..39ec879d4 --- /dev/null +++ b/crypto/ed25519/ed25519_test.go @@ -0,0 +1,27 @@ +package ed25519_test + +import ( + "testing" + + "github.com/pactus-project/pactus/crypto" + "github.com/pactus-project/pactus/crypto/ed25519" + "github.com/stretchr/testify/assert" +) + +func TestSigning(t *testing.T) { + 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.AccountAddress()) +} 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..00576fd54 --- /dev/null +++ b/crypto/ed25519/private_key.go @@ -0,0 +1,102 @@ +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 Ed25519 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) +} + +// 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..d8a4fac2f --- /dev/null +++ b/crypto/ed25519/private_key_test.go @@ -0,0 +1,77 @@ +package ed25519_test + +import ( + "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() + _, prv3 := ts.RandBLSKeyPair() + + assert.True(t, prv1.EqualsTo(prv1)) + assert.False(t, prv1.EqualsTo(prv2)) + assert.False(t, prv1.EqualsTo(prv3)) +} + +func TestPrivateKeyFromString(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + result []byte + }{ + { + "invalid separator index -1", + "not_proper_encoded", + false, nil, + }, + { + "invalid checksum (expected uuk3y0 got uuk30y)", + "SECRET1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26QUUK30Y", + false, nil, + }, + { + "invalid HRP: xxx", + "XXX1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26Q8JXUV6", + false, nil, + }, + { + "invalid private key type: 4", + "SECRET1YVKPE43FDU9TC4C8LPFD4JY9METET3GEKQE7E7ECK4EJYV20WVAPQZCU0KL", + false, nil, + }, + { + "private key should be 32 bytes, but it is 31 bytes", + "SECRET1RDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CCPV3HNE", + false, nil, + }, + { + "", + "SECRET1RJ6STNTA7Y3P2QLQF8A6QCX05F2H5TFNE5RSH066KZME4WVFXKE7QW097LG", + true, + []byte{ + 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, + }, + }, + } + + 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) + } + } +} diff --git a/crypto/ed25519/public_key.go b/crypto/ed25519/public_key.go new file mode 100644 index 000000000..5978a7293 --- /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 Ed25519 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 Ed25519 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 +} + +// String returns a human-readable string for the Ed25519 public key. +func (pub *PublicKey) String() string { + str, _ := bech32m.EncodeFromBase256WithType( + crypto.PublicKeyHRP, + crypto.SignatureTypeEd25519, + 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.AddressTypeEd25519Account, 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..ac3ae817f --- /dev/null +++ b/crypto/ed25519/public_key_test.go @@ -0,0 +1,152 @@ +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/ed25519" + "github.com/pactus-project/pactus/util" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" +) + +func TestPublicKeyCBORMarshaling(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandEd25519KeyPair() + pub2 := new(ed25519.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", ed25519.PublicKeySize)) + data, _ := cbor.Marshal(inv) + assert.NoError(t, pub2.UnmarshalCBOR(data)) +} + +func TestPublicKeyEqualsTo(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandEd25519KeyPair() + pub2, _ := ts.RandEd25519KeyPair() + pub3, _ := ts.RandBLSKeyPair() + + assert.True(t, pub1.EqualsTo(pub1)) + assert.False(t, pub1.EqualsTo(pub2)) + assert.False(t, pub1.EqualsTo(pub3)) +} + +func TestPublicKeyEncoding(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub, _ := ts.RandEd25519KeyPair() + w1 := util.NewFixedWriter(20) + assert.Error(t, pub.Encode(w1)) + + 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(ed25519.PublicKeySize, w2.Bytes()) + assert.NoError(t, pub.Decode(r2)) +} + +func TestPublicKeyVerifyAddress(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub1, _ := ts.RandEd25519KeyPair() + pub2, _ := ts.RandEd25519KeyPair() + + err := pub1.VerifyAddress(pub1.AccountAddress()) + assert.NoError(t, err) + + err = pub1.VerifyAddress(pub2.AccountAddress()) + assert.Equal(t, crypto.AddressMismatchError{ + Expected: pub1.AccountAddress(), + Got: pub2.AccountAddress(), + }, err) +} + +func TestNilPublicKey(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + 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, randSig)) +} + +func TestNilSignature(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + pub, _ := ts.RandEd25519KeyPair() + randSig := ts.RandEd25519Signature() + assert.Error(t, pub.Verify(nil, nil)) + assert.Error(t, pub.Verify(nil, randSig)) +} + +func TestPublicKeyFromString(t *testing.T) { + tests := []struct { + errMsg string + encoded string + valid bool + result []byte + }{ + { + "invalid separator index -1", + "not_proper_encoded", + false, nil, + }, + { + "invalid checksum (expected ztd56p got ztd5p6)", + "public1rafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qztd5p6", + false, nil, + }, + { + "invalid HRP: xxx", + "xxx1rafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qvguamu", + false, nil, + }, + { + "public key should be 32 bytes, but it is 31 bytes", + "public1ruwz86xyvhyehy8g7wg98jsmy07cfkjp6dy8zwxa8hqtdj99hquk7xyus", + false, nil, + }, + { + "invalid public key type: 4", + "public1yafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qdnx0mf", + false, nil, + }, + { + "", + "public1rafnl324uwngqdq455ax4e52fedmfcvskkwas6wsau0u0nwj4g96qztd56p", + true, + []byte{ + 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 := 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) + 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) + } + } +} diff --git a/crypto/ed25519/signature.go b/crypto/ed25519/signature.go new file mode 100644 index 000000000..76c38b01b --- /dev/null +++ b/crypto/ed25519/signature.go @@ -0,0 +1,96 @@ +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 Ed25519 signature. +func SignatureFromString(text string) (*Signature, error) { + data, err := hex.DecodeString(text) + if err != nil { + return nil, err + } + + return SignatureFromBytes(data) +} + +// 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, + "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(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 new file mode 100644 index 000000000..1d507c08c --- /dev/null +++ b/crypto/ed25519/signature_test.go @@ -0,0 +1,128 @@ +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/ed25519" + "github.com/pactus-project/pactus/util" + "github.com/pactus-project/pactus/util/testsuite" + "github.com/stretchr/testify/assert" +) + +func TestSignatureCBORMarshaling(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv := ts.RandEd25519KeyPair() + sig1 := prv.Sign(ts.RandBytes(16)) + sig2 := new(ed25519.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", ed25519.SignatureSize)) + data, _ := cbor.Marshal(inv) + assert.NoError(t, sig2.UnmarshalCBOR(data)) +} + +func TestSignatureEqualsTo(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, 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.False(t, sig1.EqualsTo(sig3)) +} + +func TestSignatureEncoding(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + _, prv := ts.RandEd25519KeyPair() + sig := prv.Sign(ts.RandBytes(16)) + w1 := util.NewFixedWriter(20) + assert.Error(t, sig.Encode(w1)) + + 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(ed25519.SignatureSize, w2.Bytes()) + assert.NoError(t, sig.Decode(r2)) +} + +func TestVerifyingSignature(t *testing.T) { + ts := testsuite.NewTestSuite(t) + + msg := []byte("pactus") + + pb1, pv1 := ts.RandEd25519KeyPair() + pb2, pv2 := ts.RandEd25519KeyPair() + 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 TestSignatureFromString(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 64 bytes, but it is 0 bytes", + "", + false, nil, + }, + { + "", + "7d6af02f788422319781b03d7f4ed575b78c4c4dc8060ce145624fc8dc9ad92b" + + "ae2d28c70242f03a644f313009ad9cc88b5dc37d501e43279c8fbc40b973af04", + true, + []byte{ + 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 := 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) + 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) + } + } +} 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/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 +``` 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/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.go b/genesis/genesis.go index a3d017489..8e5c55fce 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" ) @@ -28,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: @@ -57,7 +60,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 +75,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 +127,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 ebdefd9eb..b9a955cbc 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) @@ -48,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) @@ -80,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) { @@ -95,7 +76,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, genesis.DefaultGenesisParams()) for addr, acc := range gen.Accounts() { assert.Equal(t, accs[addr], acc) @@ -105,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/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/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/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/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..04c4520ab 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" @@ -9,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" @@ -27,12 +27,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()) + []*validator.Validator{val}, genesis.DefaultGenesisParams()) 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 +57,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/sandbox/interface.go b/sandbox/interface.go index 8e4da284c..059ff6f5d 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" ) @@ -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 9b82e2112..ae60daf25 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), @@ -75,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 29e92987a..7bebffce5 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" @@ -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 414a5c4fe..26b36ab8c 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, @@ -135,7 +136,7 @@ func TestAccountChange(t *testing.T) { }) } -func TestAnyRecentTransaction(t *testing.T) { +func TestRecentTransaction(t *testing.T) { td := setup(t) randTx1 := td.GenerateTestTransferTx() @@ -143,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/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/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 +} diff --git a/state/execution_test.go b/state/execution_test.go index 7b6554e21..5e2a41f53 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -2,11 +2,12 @@ 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/pactus-project/pactus/util/testsuite" "github.com/stretchr/testify/assert" ) @@ -15,20 +16,18 @@ 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() - 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)) @@ -42,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) { @@ -71,7 +67,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 +79,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 +91,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 +102,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 +114,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 +126,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/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/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/mock.go b/state/mock.go index cb44ba0ad..49bf929be 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" @@ -50,7 +50,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 c0d437f5c..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() { @@ -588,7 +586,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/state/state_test.go b/state/state_test.go index 2ea3fbcc2..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" @@ -13,7 +14,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" @@ -30,7 +30,7 @@ type testData struct { state *state genValKeys []*bls.ValidatorKey - genAccKey *bls.PrivateKey + genAccKey *ed25519.PrivateKey commonTxPool *txpool.MockTxPool } @@ -55,22 +55,22 @@ 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 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, 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 +585,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 +598,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/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/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/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/tests/main_test.go b/tests/main_test.go index 45730a85f..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(util.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( 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..d0d98433b 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() @@ -217,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) @@ -302,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()) @@ -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/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 +} 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 +} diff --git a/util/testsuite/testsuite.go b/util/testsuite/testsuite.go index cfbbadc5b..7adf16dc9 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() @@ -251,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))) @@ -258,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)) + useBLSAddress := ts.RandBool() + if useBLSAddress { + 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. @@ -298,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. @@ -344,7 +369,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, @@ -476,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, } } @@ -514,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.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.PrvKey = signer - tm.PubKey = signer.PublicKeyNative() + tm.Signer = signer } } @@ -529,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 } @@ -542,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 } @@ -555,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 } @@ -569,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 } @@ -582,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 } 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) 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/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 eef29ea88..37d2c4b79 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] @@ -153,6 +153,13 @@ func (wm *Manager) GetNewAddress( var addressInfo *vault.AddressInfo switch addressType { + case crypto.AddressTypeValidator: + info, err := wlt.NewValidatorAddress(label) + if err != nil { + return nil, err + } + addressInfo = info + case crypto.AddressTypeBLSAccount: info, err := wlt.NewBLSAccountAddress(label) if err != nil { @@ -160,13 +167,17 @@ func (wm *Manager) GetNewAddress( } addressInfo = info - case crypto.AddressTypeValidator: - info, err := wlt.NewValidatorAddress(label) + case crypto.AddressTypeEd25519Account: + 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 + addressInfo = info case crypto.AddressTypeTreasury: return nil, status.Errorf(codes.InvalidArgument, "invalid address type") @@ -189,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/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 6b928bc51..81ee3e5ed 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,22 +90,27 @@ 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 + 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 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) { 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 } @@ -307,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 } @@ -318,7 +342,6 @@ func (v *Vault) ImportPrivateKey(password string, prv *bls.PrivateKey) error { } addressIndex := len(keyStore.ImportedKeys) - pub := prv.PublicKeyNative() accAddr := pub.AccountAddress() @@ -347,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, } @@ -368,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 { @@ -385,43 +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): - seed, err := bip39.NewSeedWithErrorChecking(keyStore.MasterNode.Mnemonic, "") + prvKey, err := v.deriveBLSPrivateKey(mnemonicSeed, hdPath) 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 := v.deriveEd25519PrivateKey(mnemonicSeed, hdPath) if err != nil { return nil, err } - keys[i] = prvKey case H(PurposeImportPrivateKey): - index := path.AddressIndex() - hdkeychain.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 { @@ -436,12 +450,12 @@ func (v *Vault) PrivateKeys(password string, addrs []string) ([]crypto.PrivateKe return keys, nil } -func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { - ext, err := hdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubAccount) +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.NextAccountIndex + index := v.Purposes.PurposeBLS.NextValidatorIndex ext, err = ext.DerivePath([]uint32{index}) if err != nil { return nil, err @@ -452,25 +466,25 @@ func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { return nil, err } - addr := blsPubKey.AccountAddress().String() - data := AddressInfo{ + addr := blsPubKey.ValidatorAddress().String() + info := AddressInfo{ Address: addr, Label: label, PublicKey: blsPubKey.String(), Path: addresspath.NewPath(ext.Path()...).String(), } - v.Addresses[addr] = data - v.Purposes.PurposeBLS.NextAccountIndex++ + v.Addresses[addr] = info + v.Purposes.PurposeBLS.NextValidatorIndex++ - return &data, nil + return &info, nil } -func (v *Vault) NewValidatorAddress(label string) (*AddressInfo, error) { - ext, err := hdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubValidator) +func (v *Vault) NewBLSAccountAddress(label string) (*AddressInfo, error) { + ext, err := blshdkeychain.NewKeyFromString(v.Purposes.PurposeBLS.XPubAccount) if err != nil { return nil, err } - index := v.Purposes.PurposeBLS.NextValidatorIndex + index := v.Purposes.PurposeBLS.NextAccountIndex ext, err = ext.DerivePath([]uint32{index}) if err != nil { return nil, err @@ -481,75 +495,63 @@ func (v *Vault) NewValidatorAddress(label string) (*AddressInfo, error) { return nil, err } - addr := blsPubKey.ValidatorAddress().String() - data := AddressInfo{ + addr := blsPubKey.AccountAddress().String() + info := 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.PurposeBLS.NextAccountIndex++ - 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] - if !ok { - return nil +func (v *Vault) NewEd25519AccountAddress(label, password string) (*AddressInfo, error) { + seed, err := v.MnemonicSeed(password) + if err != nil { + return nil, err } - path, err := addresspath.FromString(info.Path) + masterKey, err := ed25519hdkeychain.NewMaster(seed) if err != nil { - return nil + return nil, err } - // TODO it would be better to return error in future - if path.CoinType() != H(v.CoinType) { - return nil + index := v.Purposes.PurposeBIP44.NextEd25519Index + ext, err := masterKey.DerivePath([]uint32{ + H(PurposeBIP44), + H(v.CoinType), + H(crypto.AddressTypeEd25519Account), + H(index), + }) + if err != nil { + return nil, err } - 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 := hdkeychain.NewKeyFromString(xPub) - if err != nil { - return nil - } - - p, err := addresspath.FromString(info.Path) - if err != nil { - return nil - } + ed25519PubKey, err := ed25519.PublicKeyFromBytes(ext.RawPublicKey()) + if err != nil { + return nil, err + } - extendedKey, err := ext.Derive(p.AddressIndex()) - if err != nil { - return nil - } + addr := ed25519PubKey.AccountAddress().String() + info := AddressInfo{ + Address: addr, + Label: label, + PublicKey: ed25519PubKey.String(), + Path: addresspath.NewPath(ext.Path()...).String(), + } + v.Addresses[addr] = info + v.Purposes.PurposeBIP44.NextEd25519Index++ - blsPubKey, err := bls.PublicKeyFromBytes(extendedKey.RawPublicKey()) - if err != nil { - return nil - } + return &info, nil +} - info.PublicKey = blsPubKey.String() - case H(PurposeImportPrivateKey): - default: +// AddressInfo like it can return bls.PublicKey instead of string. +func (v *Vault) AddressInfo(addr string) *AddressInfo { + info, ok := v.Addresses[addr] + if !ok { return nil } @@ -561,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 @@ -572,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 @@ -581,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 @@ -612,3 +614,34 @@ func (v *Vault) encryptKeyStore(keyStore *keyStore, password string) error { return nil } + +func (*Vault) deriveBLSPrivateKey(mnemonicSeed []byte, path []uint32) (*bls.PrivateKey, error) { + masterKey, err := blshdkeychain.NewMaster(mnemonicSeed, 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 (*Vault) deriveEd25519PrivateKey(mnemonicSeed []byte, path []uint32) (*ed25519.PrivateKey, error) { + masterKey, err := ed25519hdkeychain.NewMaster(mnemonicSeed) + 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..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,6 +218,21 @@ func TestAllImportedPrivateKeysAddresses(t *testing.T) { } } +func TestNewValidatorAddress(t *testing.T) { + td := setup(t) + + label := td.RandString(16) + 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'/1'") + assert.Equal(t, label, addressInfo.Label) + + pub, _ := bls.PublicKeyFromString(addressInfo.PublicKey) + assert.Equal(t, pub.ValidatorAddress().String(), addressInfo.Address) +} + func TestNewBLSAccountAddress(t *testing.T) { td := setup(t) @@ -229,18 +243,22 @@ func TestNewBLSAccountAddress(t *testing.T) { assert.NotEmpty(t, addressInfo.PublicKey) assert.Contains(t, addressInfo.Path, "m/12381'/21888'/2'") assert.Equal(t, label, addressInfo.Label) + + 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) { @@ -256,13 +274,11 @@ func TestRecover(t *testing.T) { assert.NoError(t, err) // Recover addresses - _, err = recovered.NewBLSAccountAddress("addr-1") - assert.NoError(t, err) - _, err = recovered.NewBLSAccountAddress("addr-2") + _, err = recovered.NewBLSAccountAddress("bls-account-address") assert.NoError(t, err) - _, err = recovered.NewValidatorAddress("addr-3") + _, err = recovered.NewEd25519AccountAddress("ed25519-account-address", "") 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) @@ -295,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") + } } }) } @@ -305,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())) }) @@ -430,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 ed54e7c71..bafa18e9a 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -19,12 +19,13 @@ import ( ) const ( - AddressTypeBLSAccount string = "bls_account" - AddressTypeValidator string = "validator" + AddressTypeBLSAccount string = "bls_account" + AddressTypeEd25519Account string = "ed25519_account" + AddressTypeValidator string = "validator" ) type Wallet struct { - store *store + store *Store path string grpcClient *grpcClient } @@ -53,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 { @@ -94,8 +104,8 @@ func Create(walletPath, mnemonic, password string, chain genesis.ChainType, opti return nil, ErrInvalidNetwork } - store := &store{ - Version: 1, + store := &Store{ + Version: Version2, UUID: uuid.New(), CreatedAt: time.Now().Round(time.Second).UTC(), Network: chain, @@ -118,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" @@ -379,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) { @@ -402,6 +412,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) { @@ -473,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) } @@ -485,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 +} diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 95941154d..c486820c0 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -96,9 +96,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, }) }) @@ -163,7 +163,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() @@ -189,7 +189,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) @@ -256,7 +256,7 @@ func TestStake(t *testing.T) { }) } -func TestSigningTx(t *testing.T) { +func TestSigningTxWithBLS(t *testing.T) { td := setup(t) defer td.Close() @@ -285,6 +285,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() 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/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/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 aef588647..61e84f968 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

    @@ -65,7 +115,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 "" -}} @@ -100,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 "" -}} @@ -120,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 "" -}} @@ -140,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/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 +} diff --git a/www/grpc/gen/dart/blockchain.pb.dart b/www/grpc/gen/dart/blockchain.pb.dart index 34e41f776..32465c8d3 100644 --- a/www/grpc/gen/dart/blockchain.pb.dart +++ b/www/grpc/gen/dart/blockchain.pb.dart @@ -1026,15 +1026,20 @@ 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(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({ + Proposal? proposal, $core.Iterable? instances, }) { final _result = create(); + if (proposal != null) { + _result.proposal = proposal; + } if (instances != null) { _result.instances.addAll(instances); } @@ -1062,7 +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(2) + $core.List get instances => $_getList(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..4203fb851 100644 --- a/www/grpc/gen/dart/blockchain.pbjson.dart +++ b/www/grpc/gen/dart/blockchain.pbjson.dart @@ -226,12 +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': 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('ChhHZXRDb25zZW5zdXNJbmZvUmVzcG9uc2USMwoJaW5zdGFuY2VzGAEgAygLMhUucGFjdHVzLkNvbnNlbnN1c0luZm9SCWluc3RhbmNlcw=='); +final $typed_data.Uint8List getConsensusInfoResponseDescriptor = $convert.base64Decode('ChhHZXRDb25zZW5zdXNJbmZvUmVzcG9uc2USLAoIcHJvcG9zYWwYASABKAsyEC5wYWN0dXMuUHJvcG9zYWxSCHByb3Bvc2FsEjMKCWluc3RhbmNlcxgCIAMoCzIVLnBhY3R1cy5Db25zZW5zdXNJbmZvUglpbnN0YW5jZXM='); @$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 [ @@ -380,6 +394,7 @@ 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.GetAccountRequest': GetAccountRequest$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 f0250feec..b0c4bc67a 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.)
    @@ -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 @@ -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 @@ -1471,10 +1506,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 +1920,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 +1993,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 +2920,12 @@ 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.)
    • +
    • ADDRESS_TYPE_ED25519_ACCOUNT = 3 (Account address type with Ed25519 signature scheme. +Note: Generating a new Ed25519 address requires the wallet password.)
    @@ -2898,6 +2936,13 @@ public key.

    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 dd4ce6fec..ee6ec9275 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

      @@ -197,8 +247,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.)
      @@ -280,12 +330,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.)
      @@ -457,12 +507,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.)
      @@ -843,9 +893,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.)
      @@ -1026,12 +1076,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.)
      @@ -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 @@ -1424,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 @@ -1472,10 +1557,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.)
      @@ -1886,12 +1971,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.)
      @@ -1959,12 +2044,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.)
      @@ -2886,9 +2971,12 @@ 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.)
      • +
      • ADDRESS_TYPE_ED25519_ACCOUNT = 3 (Account address type with Ed25519 signature scheme. +Note: Generating a new Ed25519 address requires the wallet password.)
      @@ -2899,6 +2987,13 @@ public key.

      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 a13c249ca..70d8f6336 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"` } @@ -1133,8 +1133,10 @@ type GetConsensusInfoResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // The proposal of the consensus info. + Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` // List of consensus instances. - Instances []*ConsensusInfo `protobuf:"bytes,1,rep,name=instances,proto3" json:"instances,omitempty"` + Instances []*ConsensusInfo `protobuf:"bytes,2,rep,name=instances,proto3" json:"instances,omitempty"` } func (x *GetConsensusInfoResponse) Reset() { @@ -1169,6 +1171,13 @@ func (*GetConsensusInfoResponse) Descriptor() ([]byte, []int) { return file_blockchain_proto_rawDescGZIP(), []int{18} } +func (x *GetConsensusInfoResponse) GetProposal() *Proposal { + if x != nil { + return x.Proposal + } + return nil +} + func (x *GetConsensusInfoResponse) GetInstances() []*ConsensusInfo { if x != nil { return x.Instances @@ -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, + 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, + 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, // 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 + 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/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 30c89c687..b57a7a9c6 100644 --- a/www/grpc/gen/go/wallet.pb.go +++ b/www/grpc/gen/go/wallet.pb.go @@ -26,9 +26,16 @@ 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 + // 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. @@ -37,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, } ) @@ -352,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() { @@ -407,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 @@ -1375,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, @@ -1383,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 d8e174538..696ee802c 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"]; @@ -13051,12 +13051,39 @@ public interface GetConsensusInfoResponseOrBuilder extends // @@protoc_insertion_point(interface_extends:pactus.GetConsensusInfoResponse) com.google.protobuf.MessageOrBuilder { + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return Whether the proposal field is set. + */ + boolean hasProposal(); + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + * @return The proposal. + */ + pactus.blockchain.BlockchainOuterClass.Proposal getProposal(); + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 1 [json_name = "proposal"]; + */ + 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 getInstancesList(); @@ -13065,7 +13092,7 @@ public interface GetConsensusInfoResponseOrBuilder extends * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ pactus.blockchain.BlockchainOuterClass.ConsensusInfo getInstances(int index); /** @@ -13073,7 +13100,7 @@ public interface GetConsensusInfoResponseOrBuilder extends * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ int getInstancesCount(); /** @@ -13081,7 +13108,7 @@ public interface GetConsensusInfoResponseOrBuilder extends * List of consensus instances. * * - * repeated .pactus.ConsensusInfo instances = 1 [json_name = "instances"]; + * repeated .pactus.ConsensusInfo instances = 2 [json_name = "instances"]; */ java.util.List getInstancesOrBuilderList(); @@ -13090,7 +13117,7 @@ public interface GetConsensusInfoResponseOrBuilder extends * 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); @@ -13140,14 +13167,52 @@ protected java.lang.Object newInstance( pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse.class, pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse.Builder.class); } - public static final int INSTANCES_FIELD_NUMBER = 1; + public static final int PROPOSAL_FIELD_NUMBER = 1; + private pactus.blockchain.BlockchainOuterClass.Proposal proposal_; + /** + *
      +     * The proposal of the consensus info.
      +     * 
      + * + * .pactus.Proposal proposal = 1 [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 = 1 [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 = 1 [json_name = "proposal"]; + */ + @java.lang.Override + 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 java.util.List getInstancesList() { @@ -13158,7 +13223,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"]; */ @java.lang.Override public java.util.List @@ -13170,7 +13235,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"]; */ @java.lang.Override public int getInstancesCount() { @@ -13181,7 +13246,7 @@ public int getInstancesCount() { * 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) { @@ -13192,7 +13257,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"]; */ @java.lang.Override public pactus.blockchain.BlockchainOuterClass.ConsensusInfoOrBuilder getInstancesOrBuilder( @@ -13214,8 +13279,11 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (proposal_ != null) { + output.writeMessage(1, getProposal()); + } for (int i = 0; i < instances_.size(); i++) { - output.writeMessage(1, instances_.get(i)); + output.writeMessage(2, instances_.get(i)); } getUnknownFields().writeTo(output); } @@ -13226,9 +13294,13 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; + if (proposal_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getProposal()); + } for (int i = 0; i < instances_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, instances_.get(i)); + .computeMessageSize(2, instances_.get(i)); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -13245,6 +13317,11 @@ public boolean equals(final java.lang.Object obj) { } pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse other = (pactus.blockchain.BlockchainOuterClass.GetConsensusInfoResponse) obj; + 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; @@ -13258,6 +13335,10 @@ public int hashCode() { } int hash = 41; hash = (19 * hash) + getDescriptor().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(); @@ -13394,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 { @@ -13428,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_); @@ -13485,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()) { @@ -13538,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(), @@ -13549,7 +13651,7 @@ public Builder mergeFrom( instancesBuilder_.addMessage(m); } break; - } // case 10 + } // case 18 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -13567,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() { @@ -13584,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) { @@ -13598,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) { @@ -13612,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) { @@ -13626,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) { @@ -13647,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) { @@ -13665,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) { @@ -13685,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) { @@ -13706,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) { @@ -13724,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) { @@ -13742,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) { @@ -13761,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) { @@ -13778,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) { @@ -13795,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) { @@ -13806,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) { @@ -13820,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() { @@ -13835,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( @@ -13846,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) { @@ -13858,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() { @@ -23360,115 +23617,1073 @@ 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 + 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; @@ -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" + - "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" + "ckTime\"\031\n\027GetConsensusInfoRequest\"}\n\030Get" + + "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" + + " \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[] { "Proposal", "Instances", }); 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/java/pactus/wallet/WalletOuterClass.java b/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java index 57746fdb6..6e9fad838 100644 --- a/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java +++ b/www/grpc/gen/java/pactus/wallet/WalletOuterClass.java @@ -24,32 +24,76 @@ 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), + /** + *
      +     * 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), ; /** + *
      +     * 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; + /** + *
      +     * 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() { @@ -79,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; } } @@ -4162,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(); } /** *
      @@ -4183,6 +4248,7 @@ private GetNewAddressRequest() {
             walletName_ = "";
             addressType_ = 0;
             label_ = "";
      +      password_ = "";
           }
       
           @java.lang.Override
      @@ -4329,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() { @@ -4352,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); } @@ -4371,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; @@ -4391,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; } @@ -4408,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; @@ -4546,6 +4668,8 @@ public Builder clear() { label_ = ""; + password_ = ""; + return this; } @@ -4575,6 +4699,7 @@ public pactus.wallet.WalletOuterClass.GetNewAddressRequest buildPartial() { result.walletName_ = walletName_; result.addressType_ = addressType_; result.label_ = label_; + result.password_ = password_; onBuilt(); return result; } @@ -4634,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; @@ -4675,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 @@ -4956,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) { @@ -17249,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, @@ -17347,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 b763cfa55..4a3457f9b 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'; +} @@ -3528,7 +3550,7 @@ proto.pactus.GetConsensusInfoRequest.serializeBinaryToWriter = function(message, * @private {!Array} * @const */ -proto.pactus.GetConsensusInfoResponse.repeatedFields_ = [1]; +proto.pactus.GetConsensusInfoResponse.repeatedFields_ = [2]; @@ -3561,6 +3583,7 @@ 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) }; @@ -3600,6 +3623,11 @@ proto.pactus.GetConsensusInfoResponse.deserializeBinaryFromReader = function(msg var field = reader.getFieldNumber(); switch (field) { case 1: + 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); @@ -3633,10 +3661,18 @@ proto.pactus.GetConsensusInfoResponse.prototype.serializeBinary = function() { */ proto.pactus.GetConsensusInfoResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; + f = message.getProposal(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.pactus.Proposal.serializeBinaryToWriter + ); + } f = message.getInstancesList(); if (f.length > 0) { writer.writeRepeatedMessage( - 1, + 2, f, proto.pactus.ConsensusInfo.serializeBinaryToWriter ); @@ -3645,12 +3681,49 @@ proto.pactus.GetConsensusInfoResponse.serializeBinaryToWriter = function(message /** - * repeated ConsensusInfo instances = 1; + * optional Proposal proposal = 1; + * @return {?proto.pactus.Proposal} + */ +proto.pactus.GetConsensusInfoResponse.prototype.getProposal = function() { + return /** @type{?proto.pactus.Proposal} */ ( + jspb.Message.getWrapperField(this, proto.pactus.Proposal, 1)); +}; + + +/** + * @param {?proto.pactus.Proposal|undefined} value + * @return {!proto.pactus.GetConsensusInfoResponse} returns this +*/ +proto.pactus.GetConsensusInfoResponse.prototype.setProposal = function(value) { + return jspb.Message.setWrapperField(this, 1, 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, 1) != null; +}; + + +/** + * repeated ConsensusInfo instances = 2; * @return {!Array} */ proto.pactus.GetConsensusInfoResponse.prototype.getInstancesList = function() { return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.pactus.ConsensusInfo, 1)); + jspb.Message.getRepeatedWrapperField(this, proto.pactus.ConsensusInfo, 2)); }; @@ -3659,7 +3732,7 @@ proto.pactus.GetConsensusInfoResponse.prototype.getInstancesList = function() { * @return {!proto.pactus.GetConsensusInfoResponse} returns this */ proto.pactus.GetConsensusInfoResponse.prototype.setInstancesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); + return jspb.Message.setRepeatedWrapperField(this, 2, value); }; @@ -3669,7 +3742,7 @@ proto.pactus.GetConsensusInfoResponse.prototype.setInstancesList = function(valu * @return {!proto.pactus.ConsensusInfo} */ proto.pactus.GetConsensusInfoResponse.prototype.addInstances = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.pactus.ConsensusInfo, opt_index); + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.pactus.ConsensusInfo, opt_index); }; @@ -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/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 4fd752f31..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\"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,\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()) @@ -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/python/blockchain_pb2.pyi b/www/grpc/gen/python/blockchain_pb2.pyi new file mode 100644 index 000000000..27b2a9848 --- /dev/null +++ b/www/grpc/gen/python/blockchain_pb2.pyi @@ -0,0 +1,290 @@ +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__ = ("proposal", "instances") + PROPOSAL_FIELD_NUMBER: _ClassVar[int] + INSTANCES_FIELD_NUMBER: _ClassVar[int] + proposal: Proposal + instances: _containers.RepeatedCompositeFieldContainer[ConsensusInfo] + def __init__(self, proposal: _Optional[_Union[Proposal, _Mapping]] = ..., 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: ... + +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/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.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 new file mode 100644 index 000000000..7cb1ab386 --- /dev/null +++ b/www/grpc/gen/python/wallet_pb2.pyi @@ -0,0 +1,195 @@ +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_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") + 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", "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 + 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") + 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: ... diff --git a/www/grpc/gen/rust/pactus.rs b/www/grpc/gen/rust/pactus.rs index 36ce81831..f5f5e27b2 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, } @@ -545,8 +545,11 @@ pub struct GetConsensusInfoRequest { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetConsensusInfoResponse { + /// The proposal of the consensus info. + #[prost(message, optional, tag="1")] + pub proposal: ::core::option::Option, /// List of consensus instances. - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag="2")] pub instances: ::prost::alloc::vec::Vec, } /// Request message to retrieve transactions in the transaction pool. @@ -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)] @@ -1042,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)] @@ -1218,9 +1241,16 @@ 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, + /// 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. @@ -1232,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. @@ -1240,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 8b34387f3..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,10 +3194,16 @@ impl serde::Serialize for GetConsensusInfoResponse { { use serde::ser::SerializeStruct; let mut len = 0; + if self.proposal.is_some() { + len += 1; + } if !self.instances.is_empty() { 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)?; } @@ -3208,11 +3217,13 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ + "proposal", "instances", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { + Proposal, Instances, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -3235,6 +3246,7 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { E: serde::de::Error, { match value { + "proposal" => Ok(GeneratedField::Proposal), "instances" => Ok(GeneratedField::Instances), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } @@ -3255,9 +3267,16 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { where V: serde::de::MapAccess<'de>, { + let mut proposal__ = None; let mut instances__ = None; while let Some(k) = map.next_key()? { match k { + 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")); @@ -3267,6 +3286,7 @@ impl<'de> serde::Deserialize<'de> for GetConsensusInfoResponse { } } Ok(GetConsensusInfoResponse { + proposal: proposal__, instances: instances__.unwrap_or_default(), }) } @@ -3599,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)?; @@ -3611,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() } } @@ -3626,6 +3652,7 @@ impl<'de> serde::Deserialize<'de> for GetNewAddressRequest { "address_type", "addressType", "label", + "password", ]; #[allow(clippy::enum_variant_names)] @@ -3633,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 @@ -3657,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)), } } @@ -3679,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 => { @@ -3699,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(), }) } } @@ -7856,6 +7893,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/proto/wallet.proto b/www/grpc/proto/wallet.proto index b6dd88b1b..8b8c7d88a 100644 --- a/www/grpc/proto/wallet.proto +++ b/www/grpc/proto/wallet.proto @@ -48,9 +48,16 @@ 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; + // 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. @@ -101,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 a5f84b7c6..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.", + "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." + "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", @@ -1628,7 +1637,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." @@ -1636,6 +1645,10 @@ "pactusGetConsensusInfoResponse": { "type": "object", "properties": { + "proposal": { + "$ref": "#/definitions/pactusProposal", + "description": "The proposal of the consensus info." + }, "instances": { "type": "array", "items": { @@ -2115,6 +2128,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/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 { 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()) }