Merge pull request #1572 from nspcc-dev/getunclaimed

Return FP strings for getunclaimedgas
This commit is contained in:
Roman Khimov 2020-12-09 14:36:37 +03:00 committed by GitHub
commit d5006c60ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 205 additions and 104 deletions

View file

@ -4,13 +4,13 @@ import (
"flag" "flag"
"strings" "strings"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
// Fixed8 is a wrapper for Uint160 with flag.Value methods. // Fixed8 is a wrapper for Uint160 with flag.Value methods.
type Fixed8 struct { type Fixed8 struct {
Value util.Fixed8 Value fixedn.Fixed8
} }
// Fixed8Flag is a flag with type string. // Fixed8Flag is a flag with type string.
@ -32,7 +32,7 @@ func (a Fixed8) String() string {
// Set implements flag.Value interface. // Set implements flag.Value interface.
func (a *Fixed8) Set(s string) error { func (a *Fixed8) Set(s string) error {
f, err := util.Fixed8FromString(s) f, err := fixedn.Fixed8FromString(s)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(err, 1)
} }
@ -41,7 +41,7 @@ func (a *Fixed8) Set(s string) error {
} }
// Fixed8 casts address to util.Fixed8. // Fixed8 casts address to util.Fixed8.
func (a *Fixed8) Fixed8() util.Fixed8 { func (a *Fixed8) Fixed8() fixedn.Fixed8 {
return a.Value return a.Value
} }
@ -70,6 +70,6 @@ func (f Fixed8Flag) Apply(set *flag.FlagSet) {
} }
// Fixed8FromContext returns parsed util.Fixed8 value provided flag name. // Fixed8FromContext returns parsed util.Fixed8 value provided flag name.
func Fixed8FromContext(ctx *cli.Context, name string) util.Fixed8 { func Fixed8FromContext(ctx *cli.Context, name string) fixedn.Fixed8 {
return ctx.Generic(name).(*Fixed8).Value return ctx.Generic(name).(*Fixed8).Value
} }

View file

@ -5,12 +5,12 @@ import (
"io/ioutil" "io/ioutil"
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestFixed8_String(t *testing.T) { func TestFixed8_String(t *testing.T) {
value := util.Fixed8(123) value := fixedn.Fixed8(123)
f := Fixed8{ f := Fixed8{
Value: value, Value: value,
} }
@ -19,7 +19,7 @@ func TestFixed8_String(t *testing.T) {
} }
func TestFixed8_Set(t *testing.T) { func TestFixed8_Set(t *testing.T) {
value := util.Fixed8(123) value := fixedn.Fixed8(123)
f := Fixed8{} f := Fixed8{}
require.Error(t, f.Set("not-a-fixed8")) require.Error(t, f.Set("not-a-fixed8"))
@ -30,10 +30,10 @@ func TestFixed8_Set(t *testing.T) {
func TestFixed8_Fixed8(t *testing.T) { func TestFixed8_Fixed8(t *testing.T) {
f := Fixed8{ f := Fixed8{
Value: util.Fixed8(123), Value: fixedn.Fixed8(123),
} }
require.Equal(t, util.Fixed8(123), f.Fixed8()) require.Equal(t, fixedn.Fixed8(123), f.Fixed8())
} }
func TestFixed8Flag_String(t *testing.T) { func TestFixed8Flag_String(t *testing.T) {

View file

@ -10,7 +10,7 @@ import (
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -47,7 +47,7 @@ func TestNEP17Balance(t *testing.T) {
e.checkNextLine(t, "^\\s*Account\\s+"+validatorAddr) e.checkNextLine(t, "^\\s*Account\\s+"+validatorAddr)
e.checkNextLine(t, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)") e.checkNextLine(t, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
b := e.Chain.GetUtilityTokenBalance(validatorHash) b := e.Chain.GetUtilityTokenBalance(validatorHash)
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+util.Fixed8(b.Int64()).String()) e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(b.Int64()).String())
}) })
t.Run("all accounts", func(t *testing.T) { t.Run("all accounts", func(t *testing.T) {
e.Run(t, cmdbase...) e.Run(t, cmdbase...)
@ -56,7 +56,7 @@ func TestNEP17Balance(t *testing.T) {
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr1)) e.checkNextLine(t, "^Account "+address.Uint160ToString(addr1))
e.checkNextLine(t, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)") e.checkNextLine(t, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
balance := e.Chain.GetUtilityTokenBalance(addr1) balance := e.Chain.GetUtilityTokenBalance(addr1)
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+util.Fixed8(balance.Int64()).String()) e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String())
e.checkNextLine(t, "^\\s*Updated:") e.checkNextLine(t, "^\\s*Updated:")
e.checkNextLine(t, "^\\s*$") e.checkNextLine(t, "^\\s*$")
@ -74,7 +74,7 @@ func TestNEP17Balance(t *testing.T) {
if strings.Contains(line, "GAS") { if strings.Contains(line, "GAS") {
e.checkLine(t, line, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)") e.checkLine(t, line, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
balance = e.Chain.GetUtilityTokenBalance(addr3) balance = e.Chain.GetUtilityTokenBalance(addr3)
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+util.Fixed8(balance.Int64()).String()) e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String())
e.checkNextLine(t, "^\\s*Updated:") e.checkNextLine(t, "^\\s*Updated:")
} else { } else {
balance, index := e.Chain.GetGoverningTokenBalance(validatorHash) balance, index := e.Chain.GetGoverningTokenBalance(validatorHash)
@ -156,7 +156,7 @@ func TestNEP17MultiTransfer(t *testing.T) {
b, _ := e.Chain.GetGoverningTokenBalance(privs[0].GetScriptHash()) b, _ := e.Chain.GetGoverningTokenBalance(privs[0].GetScriptHash())
require.Equal(t, big.NewInt(42), b) require.Equal(t, big.NewInt(42), b)
b = e.Chain.GetUtilityTokenBalance(privs[1].GetScriptHash()) b = e.Chain.GetUtilityTokenBalance(privs[1].GetScriptHash())
require.Equal(t, big.NewInt(int64(util.Fixed8FromInt64(7))), b) require.Equal(t, big.NewInt(int64(fixedn.Fixed8FromInt64(7))), b)
b, _ = e.Chain.GetGoverningTokenBalance(privs[2].GetScriptHash()) b, _ = e.Chain.GetGoverningTokenBalance(privs[2].GetScriptHash())
require.Equal(t, big.NewInt(13), b) require.Equal(t, big.NewInt(13), b)
} }

View file

@ -19,6 +19,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -446,7 +447,7 @@ func invokeFunction(ctx *cli.Context) error {
func invokeInternal(ctx *cli.Context, signAndPush bool) error { func invokeInternal(ctx *cli.Context, signAndPush bool) error {
var ( var (
err error err error
gas util.Fixed8 gas fixedn.Fixed8
operation string operation string
params = make([]smartcontract.Parameter, 0) params = make([]smartcontract.Parameter, 0)
paramsStart = 1 paramsStart = 1

View file

@ -9,6 +9,7 @@ import (
"github.com/nspcc-dev/neo-go/cli/options" "github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/cli/paramcontext" "github.com/nspcc-dev/neo-go/cli/paramcontext"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neo-go/pkg/wallet"
@ -390,14 +391,14 @@ func multiTransferNEP17(ctx *cli.Context) error {
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("invalid address: '%s'", ss[1]), 1) return cli.NewExitError(fmt.Errorf("invalid address: '%s'", ss[1]), 1)
} }
amount, err := util.FixedNFromString(ss[2], int(token.Decimals)) amount, err := fixedn.FromString(ss[2], int(token.Decimals))
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1) return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
} }
recipients = append(recipients, client.TransferTarget{ recipients = append(recipients, client.TransferTarget{
Token: token.Hash, Token: token.Hash,
Address: addr, Address: addr,
Amount: amount, Amount: amount.Int64(),
}) })
} }
@ -437,7 +438,7 @@ func transferNEP17(ctx *cli.Context) error {
} }
} }
amount, err := util.FixedNFromString(ctx.String("amount"), int(token.Decimals)) amount, err := fixedn.FromString(ctx.String("amount"), int(token.Decimals))
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1) return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
} }
@ -445,7 +446,7 @@ func transferNEP17(ctx *cli.Context) error {
return signAndSendTransfer(ctx, c, acc, []client.TransferTarget{{ return signAndSendTransfer(ctx, c, acc, []client.TransferTarget{{
Token: token.Hash, Token: token.Hash,
Address: to, Address: to,
Amount: amount, Amount: amount.Int64(),
}}) }})
} }

View file

@ -22,6 +22,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
@ -198,7 +199,7 @@ func TestCreateBasicChain(t *testing.T) {
acc0 := wallet.NewAccountFromPrivateKey(priv0) acc0 := wallet.NewAccountFromPrivateKey(priv0)
// Prepare some transaction for future submission. // Prepare some transaction for future submission.
txSendRaw := newNEP17Transfer(bc.contracts.NEO.Hash, priv0ScriptHash, priv1.GetScriptHash(), int64(util.Fixed8FromInt64(1000))) txSendRaw := newNEP17Transfer(bc.contracts.NEO.Hash, priv0ScriptHash, priv1.GetScriptHash(), int64(fixedn.Fixed8FromInt64(1000)))
txSendRaw.ValidUntilBlock = transaction.MaxValidUntilBlockIncrement txSendRaw.ValidUntilBlock = transaction.MaxValidUntilBlockIncrement
txSendRaw.Nonce = 0x1234 txSendRaw.Nonce = 0x1234
txSendRaw.Signers = []transaction.Signer{{ txSendRaw.Signers = []transaction.Signer{{
@ -245,7 +246,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
txMoveNeo, err := testchain.NewTransferFromOwner(bc, neoHash, priv0ScriptHash, neoAmount, getNextNonce(), validUntilBlock) txMoveNeo, err := testchain.NewTransferFromOwner(bc, neoHash, priv0ScriptHash, neoAmount, getNextNonce(), validUntilBlock)
require.NoError(t, err) require.NoError(t, err)
// Move some GAS to one simple account. // Move some GAS to one simple account.
txMoveGas, err := testchain.NewTransferFromOwner(bc, gasHash, priv0ScriptHash, int64(util.Fixed8FromInt64(1000)), txMoveGas, err := testchain.NewTransferFromOwner(bc, gasHash, priv0ScriptHash, int64(fixedn.Fixed8FromInt64(1000)),
getNextNonce(), validUntilBlock) getNextNonce(), validUntilBlock)
require.NoError(t, err) require.NoError(t, err)

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
@ -173,7 +174,7 @@ type Execution struct {
type executionAux struct { type executionAux struct {
Trigger string `json:"trigger"` Trigger string `json:"trigger"`
VMState string `json:"vmstate"` VMState string `json:"vmstate"`
GasConsumed util.Fixed8 `json:"gasconsumed,string"` GasConsumed fixedn.Fixed8 `json:"gasconsumed,string"`
Stack json.RawMessage `json:"stack"` Stack json.RawMessage `json:"stack"`
Events []NotificationEvent `json:"notifications"` Events []NotificationEvent `json:"notifications"`
FaultException string `json:"exception,omitempty"` FaultException string `json:"exception,omitempty"`
@ -202,7 +203,7 @@ func (e Execution) MarshalJSON() ([]byte, error) {
return json.Marshal(&executionAux{ return json.Marshal(&executionAux{
Trigger: e.Trigger.String(), Trigger: e.Trigger.String(),
VMState: e.VMState.String(), VMState: e.VMState.String(),
GasConsumed: util.Fixed8(e.GasConsumed), GasConsumed: fixedn.Fixed8(e.GasConsumed),
Stack: st, Stack: st,
Events: e.Events, Events: e.Events,
FaultException: e.FaultException, FaultException: e.FaultException,

View file

@ -10,6 +10,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
) )
@ -301,18 +302,18 @@ func (t *Transaction) Sender() util.Uint160 {
// transactionJSON is a wrapper for Transaction and // transactionJSON is a wrapper for Transaction and
// used for correct marhalling of transaction.Data // used for correct marhalling of transaction.Data
type transactionJSON struct { type transactionJSON struct {
TxID util.Uint256 `json:"hash"` TxID util.Uint256 `json:"hash"`
Size int `json:"size"` Size int `json:"size"`
Version uint8 `json:"version"` Version uint8 `json:"version"`
Nonce uint32 `json:"nonce"` Nonce uint32 `json:"nonce"`
Sender string `json:"sender"` Sender string `json:"sender"`
SystemFee util.Fixed8 `json:"sysfee,string"` SystemFee fixedn.Fixed8 `json:"sysfee,string"`
NetworkFee util.Fixed8 `json:"netfee,string"` NetworkFee fixedn.Fixed8 `json:"netfee,string"`
ValidUntilBlock uint32 `json:"validuntilblock"` ValidUntilBlock uint32 `json:"validuntilblock"`
Attributes []Attribute `json:"attributes"` Attributes []Attribute `json:"attributes"`
Signers []Signer `json:"signers"` Signers []Signer `json:"signers"`
Script []byte `json:"script"` Script []byte `json:"script"`
Scripts []Witness `json:"witnesses"` Scripts []Witness `json:"witnesses"`
} }
// MarshalJSON implements json.Marshaler interface. // MarshalJSON implements json.Marshaler interface.
@ -328,8 +329,8 @@ func (t *Transaction) MarshalJSON() ([]byte, error) {
Signers: t.Signers, Signers: t.Signers,
Script: t.Script, Script: t.Script,
Scripts: t.Scripts, Scripts: t.Scripts,
SystemFee: util.Fixed8(t.SystemFee), SystemFee: fixedn.Fixed8(t.SystemFee),
NetworkFee: util.Fixed8(t.NetworkFee), NetworkFee: fixedn.Fixed8(t.NetworkFee),
} }
return json.Marshal(tx) return json.Marshal(tx)
} }

View file

@ -7,6 +7,7 @@ import (
"math" "math"
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -119,8 +120,8 @@ func TestMarshalUnmarshalJSONInvocationTX(t *testing.T) {
Script: []byte{1, 2, 3, 4}, Script: []byte{1, 2, 3, 4},
Attributes: []Attribute{{Type: HighPriority}}, Attributes: []Attribute{{Type: HighPriority}},
Scripts: []Witness{}, Scripts: []Witness{},
SystemFee: int64(util.Fixed8FromFloat(123.45)), SystemFee: int64(fixedn.Fixed8FromFloat(123.45)),
NetworkFee: int64(util.Fixed8FromFloat(0.123)), NetworkFee: int64(fixedn.Fixed8FromFloat(0.123)),
Trimmed: false, Trimmed: false,
} }

View file

@ -0,0 +1,80 @@
package fixedn
import (
"errors"
"fmt"
"math/big"
"strconv"
"strings"
)
const maxAllowedPrecision = 16
// ErrInvalidFormat is returned when decimal format is invalid.
var ErrInvalidFormat = errors.New("invalid decimal format")
var _pow10 []*big.Int
func init() {
var p = int64(1)
for i := 0; i <= maxAllowedPrecision; i++ {
_pow10 = append(_pow10, big.NewInt(p))
p *= 10
}
}
func pow10(n int) *big.Int {
last := len(_pow10) - 1
if n <= last {
return _pow10[n]
}
p := new(big.Int)
p.Mul(_pow10[last], _pow10[1])
for i := last + 1; i < n; i++ {
p.Mul(p, _pow10[1])
}
return p
}
// ToString converts big decimal with specified precision to string.
func ToString(bi *big.Int, precision int) string {
var dp, fp big.Int
dp.QuoRem(bi, pow10(precision), &fp)
var s = dp.String()
if fp.Sign() == 0 {
return s
}
frac := fp.Uint64()
trimmed := 0
for ; frac%10 == 0; frac /= 10 {
trimmed++
}
return s + "." + fmt.Sprintf("%0"+strconv.FormatUint(uint64(precision-trimmed), 10)+"d", frac)
}
// FromString converts string to a big decimal with specified precision.
func FromString(s string, precision int) (*big.Int, error) {
parts := strings.SplitN(s, ".", 2)
bi, ok := new(big.Int).SetString(parts[0], 10)
if !ok {
return nil, ErrInvalidFormat
}
bi.Mul(bi, pow10(precision))
if len(parts) == 1 {
return bi, nil
}
if len(parts[1]) > precision {
return nil, ErrInvalidFormat
}
fp, ok := new(big.Int).SetString(parts[1], 10)
if !ok {
return nil, ErrInvalidFormat
}
fp.Mul(fp, pow10(precision-len(parts[1])))
if bi.Sign() == -1 {
return bi.Sub(bi, fp), nil
}
return bi.Add(bi, fp), nil
}

View file

@ -0,0 +1,51 @@
package fixedn
import (
"math/big"
"testing"
"github.com/stretchr/testify/require"
)
func TestDecimalFromStringGood(t *testing.T) {
var testCases = []struct {
bi *big.Int
prec int
s string
}{
{big.NewInt(123), 2, "1.23"},
{big.NewInt(12300), 2, "123"},
{big.NewInt(1234500000), 8, "12.345"},
{big.NewInt(-12345), 3, "-12.345"},
{big.NewInt(35), 8, "0.00000035"},
{big.NewInt(1230), 5, "0.0123"},
{big.NewInt(123456789), 20, "0.00000000000123456789"},
}
for _, tc := range testCases {
t.Run(tc.s, func(t *testing.T) {
s := ToString(tc.bi, tc.prec)
require.Equal(t, tc.s, s)
bi, err := FromString(s, tc.prec)
require.NoError(t, err)
require.Equal(t, tc.bi, bi)
})
}
}
func TestDecimalFromStringBad(t *testing.T) {
var errCases = []struct {
s string
prec int
}{
{"12A", 1},
{"12.345", 2},
{"12.3A", 2},
}
for _, tc := range errCases {
t.Run(tc.s, func(t *testing.T) {
_, err := FromString(tc.s, tc.prec)
require.Error(t, err)
})
}
}

View file

@ -1,9 +1,8 @@
package util package fixedn
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"math"
"strconv" "strconv"
"strings" "strings"
@ -72,36 +71,11 @@ func Fixed8FromFloat(val float64) Fixed8 {
// Fixed8FromString parses s which must be a fixed point number // Fixed8FromString parses s which must be a fixed point number
// with precision up to 10^-8 // with precision up to 10^-8
func Fixed8FromString(s string) (Fixed8, error) { func Fixed8FromString(s string) (Fixed8, error) {
num, err := FixedNFromString(s, precision) num, err := FromString(s, precision)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return Fixed8(num), err return Fixed8(num.Int64()), err
}
// FixedNFromString parses s which must be a fixed point number
// with precision 10^-d.
func FixedNFromString(s string, precision int) (int64, error) {
parts := strings.SplitN(s, ".", 2)
d := int64(math.Pow10(precision))
ip, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil {
return 0, errInvalidString
} else if len(parts) == 1 {
return ip * d, nil
}
fp, err := strconv.ParseInt(parts[1], 10, 64)
if err != nil || fp >= d {
return 0, errInvalidString
}
for i := len(parts[1]); i < precision; i++ {
fp *= 10
}
if ip < 0 {
return ip*d - fp, nil
}
return ip*d + fp, nil
} }
// UnmarshalJSON implements the json unmarshaller interface. // UnmarshalJSON implements the json unmarshaller interface.

View file

@ -1,4 +1,4 @@
package util package fixedn
import ( import (
"encoding/json" "encoding/json"
@ -8,7 +8,6 @@ import (
"github.com/nspcc-dev/neo-go/internal/testserdes" "github.com/nspcc-dev/neo-go/internal/testserdes"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -85,20 +84,6 @@ func TestFixed8FromString(t *testing.T) {
assert.Error(t, err) assert.Error(t, err)
} }
func TestFixedNFromString(t *testing.T) {
val := "123.456"
num, err := FixedNFromString(val, 3)
require.NoError(t, err)
require.EqualValues(t, 123456, num)
num, err = FixedNFromString(val, 4)
require.NoError(t, err)
require.EqualValues(t, 1234560, num)
_, err = FixedNFromString(val, 2)
require.Error(t, err)
}
func TestSatoshi(t *testing.T) { func TestSatoshi(t *testing.T) {
satoshif8 := Satoshi() satoshif8 := Satoshi()
assert.Equal(t, "0.00000001", satoshif8.String()) assert.Equal(t, "0.00000001", satoshif8.String())

View file

@ -13,6 +13,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
@ -170,10 +171,10 @@ func (c *Client) GetBlockHeaderVerbose(hash util.Uint256) (*result.Header, error
} }
// GetBlockSysFee returns the system fees of the block, based on the specified index. // GetBlockSysFee returns the system fees of the block, based on the specified index.
func (c *Client) GetBlockSysFee(index uint32) (util.Fixed8, error) { func (c *Client) GetBlockSysFee(index uint32) (fixedn.Fixed8, error) {
var ( var (
params = request.NewRawParams(index) params = request.NewRawParams(index)
resp util.Fixed8 resp fixedn.Fixed8
) )
if err := c.performRequest("getblocksysfee", params, &resp); err != nil { if err := c.performRequest("getblocksysfee", params, &resp); err != nil {
return resp, err return resp, err
@ -473,7 +474,7 @@ func (c *Client) SubmitBlock(b block.Block) (util.Uint256, error) {
// SignAndPushInvocationTx signs and pushes given script as an invocation // SignAndPushInvocationTx signs and pushes given script as an invocation
// transaction using given wif to sign it and spending the amount of gas // transaction using given wif to sign it and spending the amount of gas
// specified. It returns a hash of the invocation transaction and an error. // specified. It returns a hash of the invocation transaction and an error.
func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee util.Fixed8, cosigners []transaction.Signer) (util.Uint256, error) { func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee fixedn.Fixed8, cosigners []transaction.Signer) (util.Uint256, error) {
var txHash util.Uint256 var txHash util.Uint256
var err error var err error

View file

@ -22,6 +22,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -285,7 +286,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
}, },
serverResponse: `{"jsonrpc":"2.0","id":1,"result":"195500"}`, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"195500"}`,
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
return util.Fixed8FromInt64(195500) return fixedn.Fixed8FromInt64(195500)
}, },
}, },
}, },
@ -642,7 +643,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
invoke: func(c *Client) (interface{}, error) { invoke: func(c *Client) (interface{}, error) {
return c.GetUnclaimedGas("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB") return c.GetUnclaimedGas("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB")
}, },
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB","unclaimed":"897299680935"}}`, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB","unclaimed":"8972.99680935"}}`,
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
addr, err := address.StringToUint160("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB") addr, err := address.StringToUint160("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB")
if err != nil { if err != nil {

View file

@ -6,7 +6,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
) )
@ -26,7 +26,7 @@ type Invoke struct {
type invokeAux struct { type invokeAux struct {
State string `json:"state"` State string `json:"state"`
GasConsumed util.Fixed8 `json:"gasconsumed,string"` GasConsumed fixedn.Fixed8 `json:"gasconsumed,string"`
Script []byte `json:"script"` Script []byte `json:"script"`
Stack json.RawMessage `json:"stack"` Stack json.RawMessage `json:"stack"`
FaultException string `json:"exception,omitempty"` FaultException string `json:"exception,omitempty"`
@ -55,7 +55,7 @@ func (r Invoke) MarshalJSON() ([]byte, error) {
} }
return json.Marshal(&invokeAux{ return json.Marshal(&invokeAux{
GasConsumed: util.Fixed8(r.GasConsumed), GasConsumed: fixedn.Fixed8(r.GasConsumed),
Script: r.Script, Script: r.Script,
State: r.State, State: r.State,
Stack: st, Stack: st,

View file

@ -6,7 +6,7 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -14,7 +14,7 @@ import (
func TestInvoke_MarshalJSON(t *testing.T) { func TestInvoke_MarshalJSON(t *testing.T) {
result := &Invoke{ result := &Invoke{
State: "HALT", State: "HALT",
GasConsumed: int64(util.Fixed8FromFloat(123.45)), GasConsumed: int64(fixedn.Fixed8FromFloat(123.45)),
Script: []byte{10}, Script: []byte{10},
Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))}, Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
FaultException: "", FaultException: "",

View file

@ -2,10 +2,11 @@ package result
import ( import (
"encoding/json" "encoding/json"
"errors" "fmt"
"math/big" "math/big"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
) )
@ -25,7 +26,7 @@ type unclaimedGas struct {
func (g UnclaimedGas) MarshalJSON() ([]byte, error) { func (g UnclaimedGas) MarshalJSON() ([]byte, error) {
gas := &unclaimedGas{ gas := &unclaimedGas{
Address: address.Uint160ToString(g.Address), Address: address.Uint160ToString(g.Address),
Unclaimed: g.Unclaimed.String(), Unclaimed: fixedn.ToString(&g.Unclaimed, 8),
} }
return json.Marshal(gas) return json.Marshal(gas)
} }
@ -36,9 +37,9 @@ func (g *UnclaimedGas) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, gas); err != nil { if err := json.Unmarshal(data, gas); err != nil {
return err return err
} }
uncl, ok := new(big.Int).SetString(gas.Unclaimed, 10) uncl, err := fixedn.FromString(gas.Unclaimed, 8)
if !ok { if err != nil {
return errors.New("failed to convert unclaimed gas") return fmt.Errorf("failed to convert unclaimed gas: %w", err)
} }
g.Unclaimed = *uncl g.Unclaimed = *uncl
addr, err := address.StringToUint160(gas.Address) addr, err := address.StringToUint160(gas.Address)

View file

@ -1,6 +1,8 @@
package rpc package rpc
import "github.com/nspcc-dev/neo-go/pkg/util" import (
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
)
type ( type (
// Config is an RPC service configuration information // Config is an RPC service configuration information
@ -10,9 +12,9 @@ type (
EnableCORSWorkaround bool `yaml:"EnableCORSWorkaround"` EnableCORSWorkaround bool `yaml:"EnableCORSWorkaround"`
// MaxGasInvoke is a maximum amount of gas which // MaxGasInvoke is a maximum amount of gas which
// can be spent during RPC call. // can be spent during RPC call.
MaxGasInvoke util.Fixed8 `yaml:"MaxGasInvoke"` MaxGasInvoke fixedn.Fixed8 `yaml:"MaxGasInvoke"`
Port uint16 `yaml:"Port"` Port uint16 `yaml:"Port"`
TLSConfig TLSConfig `yaml:"TLSConfig"` TLSConfig TLSConfig `yaml:"TLSConfig"`
} }
// TLSConfig describes SSL/TLS configuration. // TLSConfig describes SSL/TLS configuration.