wallet: implement (*Account).SignTx
It is used in both CLI and RPC.
This commit is contained in:
parent
6541bd4d42
commit
05a3625b7d
6 changed files with 44 additions and 50 deletions
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/rpc/client"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/CityOfZion/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
@ -232,7 +231,7 @@ func claimGas(ctx *cli.Context) error {
|
|||
ScriptHash: scriptHash,
|
||||
})
|
||||
|
||||
signTx(tx, acc)
|
||||
_ = acc.SignTx(tx)
|
||||
if err := c.SendRawTransaction(tx); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -433,7 +432,7 @@ func transferAsset(ctx *cli.Context) error {
|
|||
Position: 1,
|
||||
})
|
||||
|
||||
signTx(tx, acc)
|
||||
_ = acc.SignTx(tx)
|
||||
if err := c.SendRawTransaction(tx); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -495,23 +494,6 @@ func createWallet(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func signTx(tx *transaction.Transaction, acc *wallet.Account) {
|
||||
priv := acc.PrivateKey()
|
||||
sign := priv.Sign(tx.GetSignedPart())
|
||||
invoc := append([]byte{byte(opcode.PUSHBYTES64)}, sign...)
|
||||
tx.Scripts = []transaction.Witness{{
|
||||
InvocationScript: invoc,
|
||||
VerificationScript: getVerificationScript(acc),
|
||||
}}
|
||||
}
|
||||
|
||||
func getVerificationScript(acc *wallet.Account) []byte {
|
||||
if acc.Contract != nil {
|
||||
return acc.Contract.Script
|
||||
}
|
||||
return acc.PrivateKey().PublicKey().GetVerificationScript()
|
||||
}
|
||||
|
||||
func readAccountInfo() (string, string, error) {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
fmt.Print("Enter the name of the account > ")
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
||||
"github.com/CityOfZion/neo-go/pkg/network"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
@ -49,10 +49,12 @@ func prepareData(t *testing.B) []*transaction.Transaction {
|
|||
var data []*transaction.Transaction
|
||||
|
||||
wif := getWif(t)
|
||||
acc, err := wallet.NewAccountFromWIF(wif.S)
|
||||
require.NoError(t, err)
|
||||
|
||||
for n := 0; n < t.N; n++ {
|
||||
tx := getTX(t, wif)
|
||||
require.NoError(t, request.SignTx(tx, wif))
|
||||
require.NoError(t, acc.SignTx(tx))
|
||||
data = append(data, tx)
|
||||
}
|
||||
return data
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/emit"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/CityOfZion/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
)
|
||||
|
@ -276,11 +277,9 @@ func _(t *testing.T) {
|
|||
ScriptHash: priv1.GetScriptHash(),
|
||||
})
|
||||
|
||||
tx5.Scripts = []transaction.Witness{{
|
||||
InvocationScript: getInvocationScript(tx5.GetSignedPart(), priv),
|
||||
VerificationScript: priv.PublicKey().GetVerificationScript(),
|
||||
}}
|
||||
|
||||
acc, err := wallet.NewAccountFromWIF(priv.WIF())
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, acc.SignTx(tx5))
|
||||
b = bc.newBlock(newMinerTX(), tx5)
|
||||
require.NoError(t, bc.AddBlock(b))
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/wallet"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -179,7 +180,10 @@ func (c *Client) SignAndPushInvocationTx(script []byte, wif *keys.WIF, gas util.
|
|||
}
|
||||
}
|
||||
|
||||
if err = request.SignTx(tx, wif); err != nil {
|
||||
acc, err := wallet.NewAccountFromWIF(wif.S)
|
||||
if err != nil {
|
||||
return txHash, err
|
||||
} else if err = acc.SignTx(tx); err != nil {
|
||||
return txHash, errors.Wrap(err, "failed to sign tx")
|
||||
}
|
||||
txHash = tx.Hash()
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/emit"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/CityOfZion/neo-go/pkg/wallet"
|
||||
errs "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -48,7 +49,9 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac
|
|||
}
|
||||
receiverOutput = transaction.NewOutput(assetID, amount, toAddressHash)
|
||||
tx.AddOutput(receiverOutput)
|
||||
if err = SignTx(tx, &wif); err != nil {
|
||||
if acc, err := wallet.NewAccountFromWIF(wif.S); err != nil {
|
||||
return nil, err
|
||||
} else if err = acc.SignTx(tx); err != nil {
|
||||
return nil, errs.Wrap(err, "failed to sign tx")
|
||||
}
|
||||
|
||||
|
@ -77,27 +80,6 @@ func AddInputsAndUnspentsToTx(tx *transaction.Transaction, addr string, assetID
|
|||
return nil
|
||||
}
|
||||
|
||||
// SignTx signs given transaction in-place using given key.
|
||||
func SignTx(tx *transaction.Transaction, wif *keys.WIF) error {
|
||||
var witness transaction.Witness
|
||||
var err error
|
||||
|
||||
if witness.InvocationScript, err = GetInvocationScript(tx, wif); err != nil {
|
||||
return errs.Wrap(err, "failed to create invocation script")
|
||||
}
|
||||
witness.VerificationScript = wif.PrivateKey.PublicKey().GetVerificationScript()
|
||||
tx.Scripts = append(tx.Scripts, witness)
|
||||
tx.Hash()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInvocationScript returns NEO VM script containing transaction signature.
|
||||
func GetInvocationScript(tx *transaction.Transaction, wif *keys.WIF) ([]byte, error) {
|
||||
signature := wif.PrivateKey.Sign(tx.GetSignedPart())
|
||||
return append([]byte{byte(opcode.PUSHBYTES64)}, signature...), nil
|
||||
}
|
||||
|
||||
// CreateDeploymentScript returns a script that deploys given smart contract
|
||||
// with its metadata.
|
||||
func CreateDeploymentScript(avm []byte, contract *ContractDetails) ([]byte, error) {
|
||||
|
|
|
@ -7,11 +7,13 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// Account represents a NEO account. It holds the private and public key
|
||||
|
@ -122,6 +124,29 @@ func NewAccount() (*Account, error) {
|
|||
return newAccountFromPrivateKey(priv), nil
|
||||
}
|
||||
|
||||
// SignTx signs transaction t and updates it's Witnesses.
|
||||
func (a *Account) SignTx(t *transaction.Transaction) error {
|
||||
if a.privateKey == nil {
|
||||
return errors.New("account is not unlocked")
|
||||
}
|
||||
data := t.GetSignedPart()
|
||||
sign := a.privateKey.Sign(data)
|
||||
|
||||
t.Scripts = append(t.Scripts, transaction.Witness{
|
||||
InvocationScript: append([]byte{byte(opcode.PUSHBYTES64)}, sign...),
|
||||
VerificationScript: a.getVerificationScript(),
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Account) getVerificationScript() []byte {
|
||||
if a.Contract != nil {
|
||||
return a.Contract.Script
|
||||
}
|
||||
return a.PrivateKey().PublicKey().GetVerificationScript()
|
||||
}
|
||||
|
||||
// Decrypt decrypts the EncryptedWIF with the given passphrase returning error
|
||||
// if anything goes wrong.
|
||||
func (a *Account) Decrypt(passphrase string) error {
|
||||
|
|
Loading…
Reference in a new issue