This repository has been archived by the owner on Jul 20, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
consensuscmd.go
137 lines (123 loc) · 4.03 KB
/
consensuscmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package client
import (
"encoding/hex"
"encoding/json"
"fmt"
"os"
"time"
"github.com/spf13/cobra"
"github.com/threefoldtech/rivine/build"
"github.com/threefoldtech/rivine/pkg/api"
"github.com/threefoldtech/rivine/pkg/cli"
"github.com/threefoldtech/rivine/pkg/encoding/siabin"
"github.com/threefoldtech/rivine/types"
)
func createConsensusCmd(client *CommandLineClient) (*consensusCmd, *cobra.Command) {
consensusCmd := &consensusCmd{cli: client}
// create root consensus command and all subs
var (
rootCmd = &cobra.Command{
Use: "consensus",
Short: "Print the current state of consensus",
Long: "Print the current state of consensus such as current block, block height, and target.",
Run: Wrap(consensusCmd.rootCmd),
}
transactionCmd = &cobra.Command{
Use: "transaction <shortID>|<longID>",
Short: "Get an existing transaction",
Long: "Get an existing transaction from the blockchain, using its given shortID or longID.",
Run: Wrap(consensusCmd.transactionCmd),
}
)
rootCmd.AddCommand(transactionCmd)
// create flags
transactionCmd.Flags().Var(
cli.NewEncodingTypeFlag(0, &consensusCmd.transactionCfg.EncodingType, 0), "encoding",
cli.EncodingTypeFlagDescription(0))
// return root command
return consensusCmd, rootCmd
}
type consensusCmd struct {
cli *CommandLineClient
transactionCfg struct {
EncodingType cli.EncodingType
}
}
// rootCmd is the handler for the command `rivinec consensus`.
// Prints the current state of consensus.
func (consensusCmd *consensusCmd) rootCmd() {
var cg api.ConsensusGET
err := consensusCmd.cli.GetWithResponse("/consensus", &cg)
if err != nil {
cli.Die("Could not get current consensus state:", err)
}
if cg.Synced {
fmt.Printf(`Synced: %v
Block: %v
Height: %v
Target: %v
`, YesNo(cg.Synced), cg.CurrentBlock, cg.Height, cg.Target)
} else {
estimatedHeight := consensusCmd.estimatedHeightAt(time.Now())
estimatedProgress := float64(cg.Height) / float64(estimatedHeight) * 100
if estimatedProgress > 99 {
estimatedProgress = 99
}
fmt.Printf(`Synced: %v
Height: %v
Progress (estimated): %.2f%%
`, YesNo(cg.Synced), cg.Height, estimatedProgress)
}
}
// EstimatedHeightAt returns the estimated block height for the given time.
// Block height is estimated by calculating the minutes since a known block in
// the past and dividing by 10 minutes (the block time).
func (consensusCmd *consensusCmd) estimatedHeightAt(t time.Time) types.BlockHeight {
if consensusCmd.cli.Config.GenesisBlockTimestamp == 0 {
build.Critical("GenesisBlockTimestamp is undefined")
}
return estimatedHeightBetween(
int64(consensusCmd.cli.Config.GenesisBlockTimestamp),
t.Unix(),
consensusCmd.cli.Config.BlockFrequencyInSeconds,
)
}
func estimatedHeightBetween(from, to, blockFrequency int64) types.BlockHeight {
lifetimeInSeconds := to - from
if lifetimeInSeconds < blockFrequency {
return 0
}
estimatedHeight := float64(lifetimeInSeconds) / float64(blockFrequency)
return types.BlockHeight(estimatedHeight + 0.5) // round to the nearest block
}
// transactionCmd is the handler for the command `rivinec consensus transaction`.
// Prints the transaction found for the given id. If the ID is a long transaction ID, it also
// prints the short transaction ID for future reference
func (consensusCmd *consensusCmd) transactionCmd(id string) {
var txn api.ConsensusGetTransaction
err := consensusCmd.cli.GetWithResponse("/consensus/transactions/"+id, &txn)
if err != nil {
cli.Die("failed to get transaction:", err, "; ID:", id)
}
var encode func(interface{}) error
switch consensusCmd.transactionCfg.EncodingType {
case cli.EncodingTypeHuman:
e := json.NewEncoder(os.Stdout)
e.SetIndent("", " ")
encode = e.Encode
case cli.EncodingTypeJSON:
encode = json.NewEncoder(os.Stdout).Encode
case cli.EncodingTypeHex:
encode = func(v interface{}) error {
b, err := siabin.Marshal(v)
if err == nil {
fmt.Println(hex.EncodeToString(b))
}
return err
}
}
err = encode(txn)
if err != nil {
cli.Die("failed to encode transaction:", err, "; ID:", id)
}
}