forked from TrueCloudLab/neoneo-go
Merge pull request #752 from nspcc-dev/fix/fixed8
cli: implement Fixed8Flag
This commit is contained in:
commit
d742733e26
7 changed files with 99 additions and 45 deletions
75
cli/flags/fixed8.go
Normal file
75
cli/flags/fixed8.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fixed8 is a wrapper for Uint160 with flag.Value methods.
|
||||||
|
type Fixed8 struct {
|
||||||
|
Value util.Fixed8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixed8Flag is a flag with type string.
|
||||||
|
type Fixed8Flag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
Value Fixed8
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ flag.Value = (*Fixed8)(nil)
|
||||||
|
_ cli.Flag = Fixed8Flag{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// String implements fmt.Stringer interface.
|
||||||
|
func (a Fixed8) String() string {
|
||||||
|
return a.Value.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set implements flag.Value interface.
|
||||||
|
func (a *Fixed8) Set(s string) error {
|
||||||
|
f, err := util.Fixed8FromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
a.Value = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixed8 casts address to util.Fixed8.
|
||||||
|
func (a *Fixed8) Fixed8() util.Fixed8 {
|
||||||
|
return a.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults).
|
||||||
|
func (f Fixed8Flag) String() string {
|
||||||
|
var names []string
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
names = append(names, getNameHelp(name))
|
||||||
|
})
|
||||||
|
|
||||||
|
return strings.Join(names, ", ") + "\t" + f.Usage
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag.
|
||||||
|
func (f Fixed8Flag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors.
|
||||||
|
func (f Fixed8Flag) Apply(set *flag.FlagSet) {
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
set.Var(&f.Value, name, f.Usage)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixed8FromContext returns parsed util.Fixed8 value provided flag name.
|
||||||
|
func Fixed8FromContext(ctx *cli.Context, name string) util.Fixed8 {
|
||||||
|
return ctx.Generic(name).(*Fixed8Flag).Value.Fixed8()
|
||||||
|
}
|
|
@ -51,7 +51,7 @@ var (
|
||||||
Name: "address, a",
|
Name: "address, a",
|
||||||
Usage: "address to use as transaction signee (and gas source)",
|
Usage: "address to use as transaction signee (and gas source)",
|
||||||
}
|
}
|
||||||
gasFlag = cli.Float64Flag{
|
gasFlag = flags.Fixed8Flag{
|
||||||
Name: "gas, g",
|
Name: "gas, g",
|
||||||
Usage: "gas to add to the transaction",
|
Usage: "gas to add to the transaction",
|
||||||
}
|
}
|
||||||
|
@ -411,7 +411,7 @@ func invokeInternal(ctx *cli.Context, withMethod bool, signAndPush bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if signAndPush {
|
if signAndPush {
|
||||||
gas = util.Fixed8FromFloat(ctx.Float64("gas"))
|
gas = flags.Fixed8FromContext(ctx, "gas")
|
||||||
acc, err = getAccFromContext(ctx)
|
acc, err = getAccFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -593,7 +593,7 @@ func contractDeploy(ctx *cli.Context) error {
|
||||||
if len(endpoint) == 0 {
|
if len(endpoint) == 0 {
|
||||||
return cli.NewExitError(errNoEndpoint, 1)
|
return cli.NewExitError(errNoEndpoint, 1)
|
||||||
}
|
}
|
||||||
gas := util.Fixed8FromFloat(ctx.Float64("gas"))
|
gas := flags.Fixed8FromContext(ctx, "gas")
|
||||||
|
|
||||||
acc, err := getAccFromContext(ctx)
|
acc, err := getAccFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -85,7 +85,7 @@ func newNEP5Commands() []cli.Command {
|
||||||
Name: "amount",
|
Name: "amount",
|
||||||
Usage: "Amount of asset to send",
|
Usage: "Amount of asset to send",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
flags.Fixed8Flag{
|
||||||
Name: "gas",
|
Name: "gas",
|
||||||
Usage: "Amount of GAS to attach to a tx",
|
Usage: "Amount of GAS to attach to a tx",
|
||||||
},
|
},
|
||||||
|
@ -309,19 +309,9 @@ func transferNEP5(ctx *cli.Context) error {
|
||||||
emit.AppCall(w.BinWriter, token.Hash, false)
|
emit.AppCall(w.BinWriter, token.Hash, false)
|
||||||
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
||||||
|
|
||||||
var gas util.Fixed8
|
gas := flags.Fixed8FromContext(ctx, "gas")
|
||||||
if gasString := ctx.String("gas"); gasString != "" {
|
|
||||||
gas, err = util.Fixed8FromString(gasString)
|
|
||||||
if err != nil {
|
|
||||||
return cli.NewExitError(fmt.Errorf("invalid GAS amount: %v", err), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
||||||
tx.Attributes = append(tx.Attributes, transaction.Attribute{
|
tx.AddVerificationHash(from)
|
||||||
Usage: transaction.Script,
|
|
||||||
Data: from.BytesBE(),
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := request.AddInputsAndUnspentsToTx(tx, fromFlag.String(), core.UtilityTokenID(), gas, c); err != nil {
|
if err := request.AddInputsAndUnspentsToTx(tx, fromFlag.String(), core.UtilityTokenID(), gas, c); err != nil {
|
||||||
return cli.NewExitError(fmt.Errorf("can't add GAS to a tx: %v", err), 1)
|
return cli.NewExitError(fmt.Errorf("can't add GAS to a tx: %v", err), 1)
|
||||||
|
|
|
@ -559,37 +559,26 @@ func (dao *dao) StoreAsTransaction(tx *transaction.Transaction, index uint32) er
|
||||||
|
|
||||||
// IsDoubleSpend verifies that the input transactions are not double spent.
|
// IsDoubleSpend verifies that the input transactions are not double spent.
|
||||||
func (dao *dao) IsDoubleSpend(tx *transaction.Transaction) bool {
|
func (dao *dao) IsDoubleSpend(tx *transaction.Transaction) bool {
|
||||||
if len(tx.Inputs) == 0 {
|
return dao.checkUsedInputs(tx.Inputs, state.CoinSpent)
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, inputs := range transaction.GroupInputsByPrevHash(tx.Inputs) {
|
|
||||||
prevHash := inputs[0].PrevHash
|
|
||||||
unspent, err := dao.GetUnspentCoinState(prevHash)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, input := range inputs {
|
|
||||||
if int(input.PrevIndex) >= len(unspent.States) || (unspent.States[input.PrevIndex].State&state.CoinSpent) != 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDoubleClaim verifies that given claim inputs are not already claimed by another tx.
|
// IsDoubleClaim verifies that given claim inputs are not already claimed by another tx.
|
||||||
func (dao *dao) IsDoubleClaim(claim *transaction.ClaimTX) bool {
|
func (dao *dao) IsDoubleClaim(claim *transaction.ClaimTX) bool {
|
||||||
if len(claim.Claims) == 0 {
|
return dao.checkUsedInputs(claim.Claims, state.CoinClaimed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dao *dao) checkUsedInputs(inputs []transaction.Input, coin state.Coin) bool {
|
||||||
|
if len(inputs) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, inputs := range transaction.GroupInputsByPrevHash(claim.Claims) {
|
for _, inputs := range transaction.GroupInputsByPrevHash(inputs) {
|
||||||
prevHash := inputs[0].PrevHash
|
prevHash := inputs[0].PrevHash
|
||||||
unspent, err := dao.GetUnspentCoinState(prevHash)
|
unspent, err := dao.GetUnspentCoinState(prevHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
if int(input.PrevIndex) >= len(unspent.States) || (unspent.States[input.PrevIndex].State&state.CoinClaimed) != 0 {
|
if int(input.PrevIndex) >= len(unspent.States) || (unspent.States[input.PrevIndex].State&coin) != 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,14 @@ func (t *Transaction) AddInput(in *Input) {
|
||||||
t.Inputs = append(t.Inputs, *in)
|
t.Inputs = append(t.Inputs, *in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddVerificationHash adds a script attribute for transaction verification.
|
||||||
|
func (t *Transaction) AddVerificationHash(addr util.Uint160) {
|
||||||
|
t.Attributes = append(t.Attributes, Attribute{
|
||||||
|
Usage: Script,
|
||||||
|
Data: addr.BytesBE(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// DecodeBinary implements Serializable interface.
|
// DecodeBinary implements Serializable interface.
|
||||||
func (t *Transaction) DecodeBinary(br *io.BinReader) {
|
func (t *Transaction) DecodeBinary(br *io.BinReader) {
|
||||||
t.Type = TXType(br.ReadB())
|
t.Type = TXType(br.ReadB())
|
||||||
|
|
|
@ -515,11 +515,7 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return txHash, errors.Wrap(err, "failed to get address")
|
return txHash, errors.Wrap(err, "failed to get address")
|
||||||
}
|
}
|
||||||
tx.Attributes = append(tx.Attributes,
|
tx.AddVerificationHash(addr)
|
||||||
transaction.Attribute{
|
|
||||||
Usage: transaction.Script,
|
|
||||||
Data: addr.BytesBE(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = acc.SignTx(tx); err != nil {
|
if err = acc.SignTx(tx); err != nil {
|
||||||
|
|
|
@ -38,11 +38,7 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac
|
||||||
if toAddressHash, err = address.StringToUint160(toAddress); err != nil {
|
if toAddressHash, err = address.StringToUint160(toAddress); err != nil {
|
||||||
return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", toAddress)
|
return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", toAddress)
|
||||||
}
|
}
|
||||||
tx.Attributes = append(tx.Attributes,
|
tx.AddVerificationHash(fromAddressHash)
|
||||||
transaction.Attribute{
|
|
||||||
Usage: transaction.Script,
|
|
||||||
Data: fromAddressHash.BytesBE(),
|
|
||||||
})
|
|
||||||
|
|
||||||
if err = AddInputsAndUnspentsToTx(tx, fromAddress, assetID, amount, balancer); err != nil {
|
if err = AddInputsAndUnspentsToTx(tx, fromAddress, assetID, amount, balancer); err != nil {
|
||||||
return nil, errs.Wrap(err, "failed to add inputs and unspents to transaction")
|
return nil, errs.Wrap(err, "failed to add inputs and unspents to transaction")
|
||||||
|
|
Loading…
Reference in a new issue