Skip to content

Commit

Permalink
Merge pull request #3167 from oasisprotocol/tjanez/gas-amount-in-tokens
Browse files Browse the repository at this point in the history
 Pretty print transaction's gas amount in token units
  • Loading branch information
tjanez authored Aug 6, 2020
2 parents 9053680 + 2141b4f commit 1bb5b80
Show file tree
Hide file tree
Showing 18 changed files with 258 additions and 200 deletions.
1 change: 1 addition & 0 deletions .changelog/3151.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/consensus/api/transaction: Pretty-print transaction's fee amount in tokens
1 change: 1 addition & 0 deletions .changelog/3167.feature.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/staking/api/token: Initial implementation
1 change: 1 addition & 0 deletions .changelog/3167.feature.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/consensus/api/transaction: Implement `PrettyPrinter` interface for `Fee`
14 changes: 11 additions & 3 deletions go/common/prettyprint/context.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package prettyprint

// ContextKeyGenesisHash is the key to retrieve the Genesis document's hash
// value from a context.
var ContextKeyGenesisHash = contextKey("genesis/hash")
var (
// ContextKeyGenesisHash is the key to retrieve the Genesis document's hash
// value from a context.
ContextKeyGenesisHash = contextKey("genesis/hash")
// ContextKeyTokenSymbol is the key to retrieve the token's ticker symbol
// value from a context.
ContextKeyTokenSymbol = contextKey("staking/token-symbol")
// ContextKeyTokenValueExponent is the key to retrieve the token's value
// base-10 exponent from a context.
ContextKeyTokenValueExponent = contextKey("staking/token-value-exponent")
)

type contextKey string
27 changes: 27 additions & 0 deletions go/consensus/api/transaction/gas.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package transaction

import (
"context"
"fmt"
"io"

"github.com/oasisprotocol/oasis-core/go/common/errors"
"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
"github.com/oasisprotocol/oasis-core/go/staking/api/token"
)

var (
Expand All @@ -12,6 +18,8 @@ var (

// ErrGasPriceTooLow is the error returned when the gas price is too low.
ErrGasPriceTooLow = errors.New(moduleName, 3, "transaction: gas price too low")

_ prettyprint.PrettyPrinter = (*Fee)(nil)
)

// Gas is the consensus gas representation.
Expand All @@ -26,6 +34,25 @@ type Fee struct {
Gas Gas `json:"gas"`
}

// PrettyPrint writes a pretty-printed representation of the fee to the given
// writer.
func (f Fee) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%sAmount: ", prefix)
token.PrettyPrintAmount(ctx, f.Amount, w)
fmt.Fprintln(w)

fmt.Fprintf(w, "%sGas limit: %d\n", prefix, f.Gas)
fmt.Fprintf(w, "%s(gas price: ", prefix)
token.PrettyPrintAmount(ctx, *f.GasPrice(), w)
fmt.Fprintln(w, " per gas unit)")
}

// PrettyType returns a representation of Fee that can be used for pretty
// printing.
func (f Fee) PrettyType() (interface{}, error) {
return f, nil
}

// GasPrice returns the gas price implied by the amount and gas.
func (f Fee) GasPrice() *quantity.Quantity {
if f.Amount.IsZero() || f.Gas == 0 {
Expand Down
3 changes: 2 additions & 1 deletion go/consensus/api/transaction/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ func (t Transaction) PrettyPrintBody(ctx context.Context, prefix string, w io.Wr
func (t Transaction) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%sNonce: %d\n", prefix, t.Nonce)
if t.Fee != nil {
fmt.Fprintf(w, "%sFee: %s (gas limit: %d, gas price: %s)\n", prefix, t.Fee.Amount, t.Fee.Gas, t.Fee.GasPrice())
fmt.Fprintf(w, "%sFee:\n", prefix)
t.Fee.PrettyPrint(ctx, prefix+" ", w)
} else {
fmt.Fprintf(w, "%sFee: none\n", prefix)
}
Expand Down
3 changes: 2 additions & 1 deletion go/genesis/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
roothashAPI "github.com/oasisprotocol/oasis-core/go/roothash/api"
scheduler "github.com/oasisprotocol/oasis-core/go/scheduler/api"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
"github.com/oasisprotocol/oasis-core/go/staking/api/token"
stakingTests "github.com/oasisprotocol/oasis-core/go/staking/tests/debug"
storage "github.com/oasisprotocol/oasis-core/go/storage/api"
)
Expand Down Expand Up @@ -670,7 +671,7 @@ func TestGenesisSanityCheck(t *testing.T) {
d.Staking.TokenSymbol = "foo"
require.EqualError(
d.SanityCheck(),
fmt.Sprintf("staking: sanity check failed: token symbol should match '%s'", staking.TokenSymbolRegexp),
fmt.Sprintf("staking: sanity check failed: token symbol should match '%s'", token.TokenSymbolRegexp),
"lower case token symbol should be rejected",
)

Expand Down
5 changes: 2 additions & 3 deletions go/oasis-node/cmd/consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
cmdConsensus "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/consensus"
cmdFlags "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/flags"
cmdGrpc "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/grpc"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
)

const (
Expand Down Expand Up @@ -137,8 +136,8 @@ func doShowTx(cmd *cobra.Command, args []string) {
genesis := cmdConsensus.InitGenesis()

ctx := context.Background()
ctx = context.WithValue(ctx, staking.PrettyPrinterContextKeyTokenSymbol, genesis.Staking.TokenSymbol)
ctx = context.WithValue(ctx, staking.PrettyPrinterContextKeyTokenValueExponent, genesis.Staking.TokenValueExponent)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenSymbol, genesis.Staking.TokenSymbol)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenValueExponent, genesis.Staking.TokenValueExponent)
ctx = context.WithValue(ctx, prettyprint.ContextKeyGenesisHash, genesis.Hash())

sigTx := loadTx()
Expand Down
43 changes: 21 additions & 22 deletions go/oasis-node/cmd/stake/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
cmdFlags "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/flags"
cmdGrpc "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/grpc"
"github.com/oasisprotocol/oasis-core/go/staking/api"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
)

const (
Expand Down Expand Up @@ -98,8 +97,8 @@ var (
// information (ticker symbol, value base-10 exponent, genesis document's hash).
func getCtxWithInfo(genesis *genesisAPI.Document) context.Context {
ctx := context.Background()
ctx = context.WithValue(ctx, staking.PrettyPrinterContextKeyTokenSymbol, genesis.Staking.TokenSymbol)
ctx = context.WithValue(ctx, staking.PrettyPrinterContextKeyTokenValueExponent, genesis.Staking.TokenValueExponent)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenSymbol, genesis.Staking.TokenSymbol)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenValueExponent, genesis.Staking.TokenValueExponent)
ctx = context.WithValue(ctx, prettyprint.ContextKeyGenesisHash, genesis.Hash())
return ctx
}
Expand All @@ -109,7 +108,7 @@ func doAccountInfo(cmd *cobra.Command, args []string) {
cmdCommon.EarlyLogAndExit(err)
}

var addr staking.Address
var addr api.Address
if err := addr.UnmarshalText([]byte(viper.GetString(CfgAccountAddr))); err != nil {
logger.Error("failed to parse account address",
"err", err,
Expand All @@ -124,8 +123,8 @@ func doAccountInfo(cmd *cobra.Command, args []string) {
acct := getAccount(ctx, cmd, addr, client)
symbol := getTokenSymbol(ctx, cmd, client)
exp := getTokenValueExponent(ctx, cmd, client)
ctx = context.WithValue(ctx, api.PrettyPrinterContextKeyTokenSymbol, symbol)
ctx = context.WithValue(ctx, api.PrettyPrinterContextKeyTokenValueExponent, exp)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenSymbol, symbol)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenValueExponent, exp)
acct.PrettyPrint(ctx, "", os.Stdout)
}

Expand All @@ -137,7 +136,7 @@ func doAccountTransfer(cmd *cobra.Command, args []string) {
genesis := cmdConsensus.InitGenesis()
cmdConsensus.AssertTxFileOK()

var xfer staking.Transfer
var xfer api.Transfer
if err := xfer.To.UnmarshalText([]byte(viper.GetString(CfgTransferDestination))); err != nil {
logger.Error("failed to parse transfer destination account address",
"err", err,
Expand All @@ -152,7 +151,7 @@ func doAccountTransfer(cmd *cobra.Command, args []string) {
}

nonce, fee := cmdConsensus.GetTxNonceAndFee()
tx := staking.NewTransferTx(nonce, fee, &xfer)
tx := api.NewTransferTx(nonce, fee, &xfer)

cmdConsensus.SignAndSaveTx(getCtxWithInfo(genesis), tx)
}
Expand All @@ -165,7 +164,7 @@ func doAccountBurn(cmd *cobra.Command, args []string) {
genesis := cmdConsensus.InitGenesis()
cmdConsensus.AssertTxFileOK()

var burn staking.Burn
var burn api.Burn
if err := burn.Amount.UnmarshalText([]byte(viper.GetString(CfgAmount))); err != nil {
logger.Error("failed to parse burn amount",
"err", err,
Expand All @@ -174,7 +173,7 @@ func doAccountBurn(cmd *cobra.Command, args []string) {
}

nonce, fee := cmdConsensus.GetTxNonceAndFee()
tx := staking.NewBurnTx(nonce, fee, &burn)
tx := api.NewBurnTx(nonce, fee, &burn)

cmdConsensus.SignAndSaveTx(getCtxWithInfo(genesis), tx)
}
Expand All @@ -187,7 +186,7 @@ func doAccountEscrow(cmd *cobra.Command, args []string) {
genesis := cmdConsensus.InitGenesis()
cmdConsensus.AssertTxFileOK()

var escrow staking.Escrow
var escrow api.Escrow
if err := escrow.Account.UnmarshalText([]byte(viper.GetString(CfgEscrowAccount))); err != nil {
logger.Error("failed to parse escrow account",
"err", err,
Expand All @@ -202,7 +201,7 @@ func doAccountEscrow(cmd *cobra.Command, args []string) {
}

nonce, fee := cmdConsensus.GetTxNonceAndFee()
tx := staking.NewAddEscrowTx(nonce, fee, &escrow)
tx := api.NewAddEscrowTx(nonce, fee, &escrow)

cmdConsensus.SignAndSaveTx(getCtxWithInfo(genesis), tx)
}
Expand All @@ -215,7 +214,7 @@ func doAccountReclaimEscrow(cmd *cobra.Command, args []string) {
genesis := cmdConsensus.InitGenesis()
cmdConsensus.AssertTxFileOK()

var reclaim staking.ReclaimEscrow
var reclaim api.ReclaimEscrow
if err := reclaim.Account.UnmarshalText([]byte(viper.GetString(CfgEscrowAccount))); err != nil {
logger.Error("failed to parse escrow account",
"err", err,
Expand All @@ -230,12 +229,12 @@ func doAccountReclaimEscrow(cmd *cobra.Command, args []string) {
}

nonce, fee := cmdConsensus.GetTxNonceAndFee()
tx := staking.NewReclaimEscrowTx(nonce, fee, &reclaim)
tx := api.NewReclaimEscrowTx(nonce, fee, &reclaim)

cmdConsensus.SignAndSaveTx(getCtxWithInfo(genesis), tx)
}

func scanRateStep(dst *staking.CommissionRateStep, raw string) error {
func scanRateStep(dst *api.CommissionRateStep, raw string) error {
var rateBI big.Int
n, err := fmt.Sscanf(raw, "%d/%d", &dst.Start, &rateBI)
if err != nil {
Expand All @@ -250,7 +249,7 @@ func scanRateStep(dst *staking.CommissionRateStep, raw string) error {
return nil
}

func scanBoundStep(dst *staking.CommissionRateBoundStep, raw string) error {
func scanBoundStep(dst *api.CommissionRateBoundStep, raw string) error {
var rateMinBI big.Int
var rateMaxBI big.Int
n, err := fmt.Sscanf(raw, "%d/%d/%d", &dst.Start, &rateMinBI, &rateMaxBI)
Expand All @@ -277,10 +276,10 @@ func doAccountAmendCommissionSchedule(cmd *cobra.Command, args []string) {
genesis := cmdConsensus.InitGenesis()
cmdConsensus.AssertTxFileOK()

var amendCommissionSchedule staking.AmendCommissionSchedule
var amendCommissionSchedule api.AmendCommissionSchedule
rawRates := viper.GetStringSlice(CfgCommissionScheduleRates)
if rawRates != nil {
amendCommissionSchedule.Amendment.Rates = make([]staking.CommissionRateStep, len(rawRates))
amendCommissionSchedule.Amendment.Rates = make([]api.CommissionRateStep, len(rawRates))
for i, rawRate := range rawRates {
if err := scanRateStep(&amendCommissionSchedule.Amendment.Rates[i], rawRate); err != nil {
logger.Error("failed to parse commission schedule rate step",
Expand All @@ -294,7 +293,7 @@ func doAccountAmendCommissionSchedule(cmd *cobra.Command, args []string) {
}
rawBounds := viper.GetStringSlice(CfgCommissionScheduleBounds)
if rawBounds != nil {
amendCommissionSchedule.Amendment.Bounds = make([]staking.CommissionRateBoundStep, len(rawBounds))
amendCommissionSchedule.Amendment.Bounds = make([]api.CommissionRateBoundStep, len(rawBounds))
for i, rawBound := range rawBounds {
if err := scanBoundStep(&amendCommissionSchedule.Amendment.Bounds[i], rawBound); err != nil {
logger.Error("failed to parse commission schedule bound step",
Expand All @@ -308,7 +307,7 @@ func doAccountAmendCommissionSchedule(cmd *cobra.Command, args []string) {
}

nonce, fee := cmdConsensus.GetTxNonceAndFee()
tx := staking.NewAmendCommissionScheduleTx(nonce, fee, &amendCommissionSchedule)
tx := api.NewAmendCommissionScheduleTx(nonce, fee, &amendCommissionSchedule)

cmdConsensus.SignAndSaveTx(getCtxWithInfo(genesis), tx)
}
Expand Down Expand Up @@ -364,13 +363,13 @@ func init() {
commissionScheduleFlags.StringSlice(CfgCommissionScheduleRates, nil, fmt.Sprintf(
"commission rate step. Multiple of this flag is allowed. "+
"Each step is in the format start_epoch/rate_numerator. "+
"The rate is rate_numerator divided by %v", staking.CommissionRateDenominator,
"The rate is rate_numerator divided by %v", api.CommissionRateDenominator,
))
commissionScheduleFlags.StringSlice(CfgCommissionScheduleBounds, nil, fmt.Sprintf(
"commission rate bound step. Multiple of this flag is allowed. "+
"Each step is in the format start_epoch/rate_min_numerator/rate_max_numerator. "+
"The minimum rate is rate_min_numerator divided by %v, and the maximum rate is "+
"rate_max_numerator divided by %v", staking.CommissionRateDenominator, staking.CommissionRateDenominator,
"rate_max_numerator divided by %v", api.CommissionRateDenominator, api.CommissionRateDenominator,
))
_ = viper.BindPFlags(commissionScheduleFlags)
commissionScheduleFlags.AddFlagSet(cmdConsensus.TxFlags)
Expand Down
17 changes: 9 additions & 8 deletions go/oasis-node/cmd/stake/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/errors"
"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
cmdCommon "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common"
cmdFlags "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/flags"
cmdGrpc "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/grpc"
"github.com/oasisprotocol/oasis-core/go/staking/api"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
"github.com/oasisprotocol/oasis-core/go/staking/api/token"
)

// CfgPublicKey configures the public key.
Expand Down Expand Up @@ -120,8 +121,8 @@ func doInfo(cmd *cobra.Command, args []string) {
exp := getTokenValueExponent(ctx, cmd, client)
fmt.Printf("Token's value base-10 exponent: %d\n", exp)

ctx = context.WithValue(ctx, api.PrettyPrinterContextKeyTokenSymbol, symbol)
ctx = context.WithValue(ctx, api.PrettyPrinterContextKeyTokenValueExponent, exp)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenSymbol, symbol)
ctx = context.WithValue(ctx, prettyprint.ContextKeyTokenValueExponent, exp)

totalSupply, err := client.TotalSupply(ctx, consensus.HeightLatest)
if err != nil {
Expand All @@ -131,7 +132,7 @@ func doInfo(cmd *cobra.Command, args []string) {
os.Exit(1)
}
fmt.Print("Total supply: ")
api.PrettyPrintAmount(ctx, *totalSupply, os.Stdout)
token.PrettyPrintAmount(ctx, *totalSupply, os.Stdout)
fmt.Println()

commonPool, err := client.CommonPool(ctx, consensus.HeightLatest)
Expand All @@ -142,7 +143,7 @@ func doInfo(cmd *cobra.Command, args []string) {
os.Exit(1)
}
fmt.Print("Common pool: ")
api.PrettyPrintAmount(ctx, *commonPool, os.Stdout)
token.PrettyPrintAmount(ctx, *commonPool, os.Stdout)
fmt.Println()

lastBlockFees, err := client.LastBlockFees(ctx, consensus.HeightLatest)
Expand All @@ -153,7 +154,7 @@ func doInfo(cmd *cobra.Command, args []string) {
os.Exit(1)
}
fmt.Print("Last block fees: ")
api.PrettyPrintAmount(ctx, *lastBlockFees, os.Stdout)
token.PrettyPrintAmount(ctx, *lastBlockFees, os.Stdout)
fmt.Println()

thresholdsToQuery := []api.ThresholdKind{
Expand All @@ -178,7 +179,7 @@ func doInfo(cmd *cobra.Command, args []string) {
os.Exit(1)
}
fmt.Printf("Staking threshold (%s): ", kind)
api.PrettyPrintAmount(ctx, *thres, os.Stdout)
token.PrettyPrintAmount(ctx, *thres, os.Stdout)
fmt.Println()
}
}
Expand Down Expand Up @@ -238,7 +239,7 @@ func doPubkey2Address(cmd *cobra.Command, args []string) {
os.Exit(1)
}

fmt.Printf("%v\n", staking.NewAddress(pk))
fmt.Printf("%v\n", api.NewAddress(pk))
}

// Register registers the stake sub-command and all of it's children.
Expand Down
5 changes: 3 additions & 2 deletions go/oasis-test-runner/scenario/e2e/stake_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/entity"
"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
genesisTestHelpers "github.com/oasisprotocol/oasis-core/go/genesis/tests"
Expand Down Expand Up @@ -96,12 +97,12 @@ func contextWithTokenInfo() context.Context {
ctx := context.Background()
ctx = context.WithValue(
ctx,
api.PrettyPrinterContextKeyTokenSymbol,
prettyprint.ContextKeyTokenSymbol,
genesisTestHelpers.TestStakingTokenSymbol,
)
ctx = context.WithValue(
ctx,
api.PrettyPrinterContextKeyTokenValueExponent,
prettyprint.ContextKeyTokenValueExponent,
genesisTestHelpers.TestStakingTokenValueExponent,
)
return ctx
Expand Down
Loading

0 comments on commit 1bb5b80

Please sign in to comment.