From 4860375c526218fb621749397aff39ab875b6037 Mon Sep 17 00:00:00 2001 From: Will Winder Date: Wed, 8 Dec 2021 23:06:52 -0500 Subject: Compatibility mode for partkeyinfo. (#3291) ## Summary Compatibility for `partkeyinfo` was also needed by some users. In addition to the different format, the old command also allows printing key information when the node is not running Workarounds: 1) use an older `goal` binary. 2) use `algokey part info --keyfile ` ## Test Plan Tested manually: ``` ~$ goal account partkeyinfo -d /tmp/private_network/Node/ Dumping participation key info from /tmp/private_network/Node/... Participation ID: CPLHRU3WEY3PE7XTPPSIE7BGJYWAIFPS7DL3HZNC4OKQRQ5YAYUA Parent address: DGS6VNX2BRMKGKVAS2LTREMYG33TOCYPFLPCQ3DUTJULQU6P6S7KJCDNTU Last vote round: 1 Last block proposal round: 2 Effective first round: 1 Effective last round: 3000000 First round: 0 Last round: 3000000 Key dilution: 10000 Selection key: 5QRrTgzSUTqqym43QVsBus1/AOwGR5zE+I7FGwA14vQ= Voting key: PK0NMyZ4BKSjPQ9JuT7dQBLdTpjLQv2txuDYDKhkuqs= ~$ goal account partkeyinfo -d /tmp/private_network/Node/ -c Dumping participation key info from /tmp/private_network/Node/... ------------------------------------------------------------------ File: Wallet2.0.3000000.partkey { "acct": "DGS6VNX2BRMKGKVAS2LTREMYG33TOCYPFLPCQ3DUTJULQU6P6S7KJCDNTU", "last": 3000000, "sel": "5QRrTgzSUTqqym43QVsBus1/AOwGR5zE+I7FGwA14vQ=", "vote": "PK0NMyZ4BKSjPQ9JuT7dQBLdTpjLQv2txuDYDKhkuqs=", "voteKD": 10000 } ``` --- cmd/goal/account.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/cmd/goal/account.go b/cmd/goal/account.go index 7d20af38f..ccc37f227 100644 --- a/cmd/goal/account.go +++ b/cmd/goal/account.go @@ -59,7 +59,7 @@ var ( partKeyOutDir string partKeyFile string partKeyDeleteInput bool - listpartkeyCompat bool + partkeyCompat bool importDefault bool mnemonic string dumpOutFile string @@ -167,7 +167,10 @@ func init() { installParticipationKeyCmd.Flags().BoolVar(&partKeyDeleteInput, "delete-input", false, "Acknowledge that installpartkey will delete the input key file") // listpartkey flags - listParticipationKeysCmd.Flags().BoolVarP(&listpartkeyCompat, "compatibility", "c", false, "Print output in compatibility mode. This option will be removed in a future release, please use REST API for tooling.") + listParticipationKeysCmd.Flags().BoolVarP(&partkeyCompat, "compatibility", "c", false, "Print output in compatibility mode. This option will be removed in a future release, please use REST API for tooling.") + + // partkeyinfo flags + partkeyInfoCmd.Flags().BoolVarP(&partkeyCompat, "compatibility", "c", false, "Print output in compatibility mode. This option will be removed in a future release, please use REST API for tooling.") // import flags importCmd.Flags().BoolVarP(&importDefault, "default", "f", false, "Set this account as the default one") @@ -1069,6 +1072,7 @@ func uintToStr(number uint64) string { // legacyListParticipationKeysCommand prints key information in the same // format as earlier versions of goal. Some users are using this information // in scripts and need some extra time to migrate to the REST API. +// DEPRECATED func legacyListParticipationKeysCommand() { dataDir := ensureSingleDataDir() @@ -1118,7 +1122,7 @@ var listParticipationKeysCmd = &cobra.Command{ Long: `List all participation keys tracked by algod along with summary of additional information. For detailed key information use 'partkeyinfo'.`, Args: validateNoPosArgsFn, Run: func(cmd *cobra.Command, args []string) { - if listpartkeyCompat { + if partkeyCompat { legacyListParticipationKeysCommand() return } @@ -1364,12 +1368,57 @@ func strOrNA(value *uint64) string { return uintToStr(*value) } +// legacyPartkeyInfoCommand prints key information in the same +// format as earlier versions of goal. Some users are using this information +// in scripts and need some extra time to migrate to alternatives. +// DEPRECATED +func legacyPartkeyInfoCommand() { + type partkeyInfo struct { + _struct struct{} `codec:",omitempty,omitemptyarray"` + Address string `codec:"acct"` + FirstValid basics.Round `codec:"first"` + LastValid basics.Round `codec:"last"` + VoteID crypto.OneTimeSignatureVerifier `codec:"vote"` + SelectionID crypto.VRFVerifier `codec:"sel"` + VoteKeyDilution uint64 `codec:"voteKD"` + } + + onDataDirs(func(dataDir string) { + fmt.Printf("Dumping participation key info from %s...\n", dataDir) + client := ensureGoalClient(dataDir, libgoal.DynamicClient) + + // Make sure we don't already have a partkey valid for (or after) specified roundLastValid + parts, err := client.ListParticipationKeyFiles() + if err != nil { + reportErrorf(errorRequestFail, err) + } + + for filename, part := range parts { + fmt.Println("------------------------------------------------------------------") + info := partkeyInfo{ + Address: part.Address().String(), + FirstValid: part.FirstValid, + LastValid: part.LastValid, + VoteID: part.VotingSecrets().OneTimeSignatureVerifier, + SelectionID: part.VRFSecrets().PK, + VoteKeyDilution: part.KeyDilution, + } + infoString := protocol.EncodeJSON(&info) + fmt.Printf("File: %s\n%s\n", filename, string(infoString)) + } + }) +} + var partkeyInfoCmd = &cobra.Command{ Use: "partkeyinfo", Short: "Output details about all available part keys", Long: `Output details about all available part keys in the specified data directory(ies), such as key validity period.`, Args: validateNoPosArgsFn, Run: func(cmd *cobra.Command, args []string) { + if partkeyCompat { + legacyPartkeyInfoCommand() + return + } onDataDirs(func(dataDir string) { fmt.Printf("Dumping participation key info from %s...\n", dataDir) -- cgit v1.2.3 From 47917068283c6a0ffef26e442d9df0c6494005aa Mon Sep 17 00:00:00 2001 From: Shant Karakashian <55754073+algonautshant@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:06:47 -0500 Subject: catchup: suspend the catchup session once the agreement service kicks in (#3299) The catchup service stops when it is complete, i.e. it has reached up to the round which is being agreed on. The catchup service knows it is complete and should stop, when it finds that a block is in the ledger before it adds it. In other words, apart from the catchup, only the agreement adds blocks to the ledger. And when the agreement adds a block to the ledger before the catchup, it means the agreement is ahead, and the catchup is complete. When `fetchAndWrite` detects the block is already in the ledger, it returns. The return value of `false` stops the catchup syncing. In previous releases, `fetchAndWrite` was only checking if the block is already in the ledger after attempting to fetch it. Since it fails to fetch a block not yet agreed on, the fetch fails after multiple attempts, and `fetchAndWrite` returns `false` ending the catchup. A recent change made this process more efficient by first checking if the block is in the ledger before/during the fetch. However, once the block was found in the ledger, `fetchAndWrite` returned true instead of false (consistent with already existing logic since forever, which was also wrong). This caused the catchup to continue syncing after catchup was complete. This change fixes the return value from true to false. --- catchup/service.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/catchup/service.go b/catchup/service.go index 27ce957ba..de4a52a94 100644 --- a/catchup/service.go +++ b/catchup/service.go @@ -241,8 +241,10 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool, if err != nil { if err == errLedgerAlreadyHasBlock { - // ledger already has the block, no need to request this block from anyone. - return true + // ledger already has the block, no need to request this block. + // only the agreement could have added this block into the ledger, catchup is complete + s.log.Infof("fetchAndWrite(%d): the block is already in the ledger. The catchup is complete", r) + return false } s.log.Debugf("fetchAndWrite(%v): Could not fetch: %v (attempt %d)", r, err, i) peerSelector.rankPeer(psp, peerRankDownloadFailed) @@ -353,8 +355,10 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool, s.log.Infof("fetchAndWrite(%d): no need to re-evaluate historical block", r) return true case ledgercore.BlockInLedgerError: - s.log.Infof("fetchAndWrite(%d): block already in ledger", r) - return true + // the block was added to the ledger from elsewhere after fetching it here + // only the agreement could have added this block into the ledger, catchup is complete + s.log.Infof("fetchAndWrite(%d): after fetching the block, it is already in the ledger. The catchup is complete", r) + return false case protocol.Error: if !s.protocolErrorLogged { logging.Base().Errorf("fetchAndWrite(%v): unrecoverable protocol error detected: %v", r, err) @@ -387,7 +391,7 @@ func (s *Service) pipelineCallback(r basics.Round, thisFetchComplete chan bool, thisFetchComplete <- fetchResult if !fetchResult { - s.log.Infof("failed to fetch block %v", r) + s.log.Infof("pipelineCallback(%d): did not fetch or write the block", r) return 0 } return r -- cgit v1.2.3 From 3ac5e0efdc66918f5fc51478c968ff98d4e42dc4 Mon Sep 17 00:00:00 2001 From: John Lee Date: Thu, 9 Dec 2021 22:21:37 -0500 Subject: Bump buildnumber.dat --- buildnumber.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildnumber.dat b/buildnumber.dat index d00491fd7..0cfbf0888 100644 --- a/buildnumber.dat +++ b/buildnumber.dat @@ -1 +1 @@ -1 +2 -- cgit v1.2.3