wallet: provide (*Account).SignHashable API

Make PrivateKey() less used and less useful.
This commit is contained in:
Roman Khimov 2022-09-01 20:42:42 +03:00
parent e569edc841
commit e164625a7f
10 changed files with 24 additions and 16 deletions

View file

@ -17,10 +17,8 @@ import (
func InitAndSave(net netmode.Magic, tx *transaction.Transaction, acc *wallet.Account, filename string) error { func InitAndSave(net netmode.Magic, tx *transaction.Transaction, acc *wallet.Account, filename string) error {
scCtx := context.NewParameterContext("Neo.Network.P2P.Payloads.Transaction", net, tx) scCtx := context.NewParameterContext("Neo.Network.P2P.Payloads.Transaction", net, tx)
if acc != nil && acc.CanSign() { if acc != nil && acc.CanSign() {
priv := acc.PrivateKey() sign := acc.SignHashable(net, tx)
pub := priv.PublicKey() if err := scCtx.AddSignature(acc.ScriptHash(), acc.Contract, acc.PublicKey(), sign); err != nil {
sign := priv.SignHashable(uint32(net), tx)
if err := scCtx.AddSignature(acc.ScriptHash(), acc.Contract, pub, sign); err != nil {
return fmt.Errorf("can't add signature: %w", err) return fmt.Errorf("can't add signature: %w", err)
} }
} }

View file

@ -58,8 +58,7 @@ func signStoredTransaction(ctx *cli.Context) error {
} }
if acc.CanSign() { if acc.CanSign() {
priv := acc.PrivateKey() sign := acc.SignHashable(pc.Network, pc.Verifiable)
sign := priv.SignHashable(uint32(pc.Network), pc.Verifiable)
if err := pc.AddSignature(ch, acc.Contract, acc.PublicKey(), sign); err != nil { if err := pc.AddSignature(ch, acc.Contract, acc.PublicKey(), sign); err != nil {
return cli.NewExitError(fmt.Errorf("can't add signature: %w", err), 1) return cli.NewExitError(fmt.Errorf("can't add signature: %w", err), 1)
} }

View file

@ -74,7 +74,7 @@ func (s *signer) ScriptHash() util.Uint160 {
// SignHashable implements Signer interface. // SignHashable implements Signer interface.
func (s *signer) SignHashable(magic uint32, item hash.Hashable) []byte { func (s *signer) SignHashable(magic uint32, item hash.Hashable) []byte {
return append([]byte{byte(opcode.PUSHDATA1), 64}, return append([]byte{byte(opcode.PUSHDATA1), 64},
(*wallet.Account)(s).PrivateKey().SignHashable(magic, item)...) (*wallet.Account)(s).SignHashable(netmode.Magic(magic), item)...)
} }
// SignTx implements Signer interface. // SignTx implements Signer interface.
@ -130,7 +130,7 @@ func (m multiSigner) Script() []byte {
func (m multiSigner) SignHashable(magic uint32, item hash.Hashable) []byte { func (m multiSigner) SignHashable(magic uint32, item hash.Hashable) []byte {
var script []byte var script []byte
for i := 0; i < m.m; i++ { for i := 0; i < m.m; i++ {
sign := m.accounts[i].PrivateKey().SignHashable(magic, item) sign := m.accounts[i].SignHashable(netmode.Magic(magic), item)
script = append(script, byte(opcode.PUSHDATA1), 64) script = append(script, byte(opcode.PUSHDATA1), 64)
script = append(script, sign...) script = append(script, sign...)
} }

View file

@ -300,7 +300,7 @@ func (a *Actor) SendRequestExactly(mainTx *transaction.Transaction, fbTx *transa
FallbackTransaction: fbTx, FallbackTransaction: fbTx,
} }
req.Witness = transaction.Witness{ req.Witness = transaction.Witness{
InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, a.sender.PrivateKey().SignHashable(uint32(a.GetNetwork()), req)...), InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, a.sender.SignHashable(a.GetNetwork(), req)...),
VerificationScript: a.sender.GetVerificationScript(), VerificationScript: a.sender.GetVerificationScript(),
} }
actualHash, err := a.rpc.SubmitP2PNotaryRequest(req) actualHash, err := a.rpc.SubmitP2PNotaryRequest(req)

View file

@ -938,7 +938,7 @@ func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fa
FallbackTransaction: fallbackTx, FallbackTransaction: fallbackTx,
} }
req.Witness = transaction.Witness{ req.Witness = transaction.Witness{
InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.PrivateKey().SignHashable(uint32(m), req)...), InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.SignHashable(m, req)...),
VerificationScript: acc.GetVerificationScript(), VerificationScript: acc.GetVerificationScript(),
} }
actualHash, err := c.SubmitP2PNotaryRequest(req) actualHash, err := c.SubmitP2PNotaryRequest(req)

View file

@ -391,7 +391,7 @@ func (n *Notary) PostPersist() {
// finalize adds missing Notary witnesses to the transaction (main or fallback) and pushes it to the network. // finalize adds missing Notary witnesses to the transaction (main or fallback) and pushes it to the network.
func (n *Notary) finalize(acc *wallet.Account, tx *transaction.Transaction, h util.Uint256) error { func (n *Notary) finalize(acc *wallet.Account, tx *transaction.Transaction, h util.Uint256) error {
notaryWitness := transaction.Witness{ notaryWitness := transaction.Witness{
InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.PrivateKey().SignHashable(uint32(n.Network), tx)...), InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.SignHashable(n.Network, tx)...),
VerificationScript: []byte{}, VerificationScript: []byte{},
} }
for i, signer := range tx.Signers { for i, signer := range tx.Signers {

View file

@ -103,7 +103,7 @@ func (s *service) sendValidatedRoot(r *state.MPTRoot, acc *wallet.Account) {
VerificationScript: acc.GetVerificationScript(), VerificationScript: acc.GetVerificationScript(),
}, },
} }
sig := acc.PrivateKey().SignHashable(uint32(s.Network), ep) sig := acc.SignHashable(s.Network, ep)
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
emit.Bytes(buf.BinWriter, sig) emit.Bytes(buf.BinWriter, sig)
ep.Witness.InvocationScript = buf.Bytes() ep.Witness.InvocationScript = buf.Bytes()

View file

@ -86,7 +86,7 @@ func (s *service) signAndSend(r *state.MPTRoot) error {
return nil return nil
} }
sig := acc.PrivateKey().SignHashable(uint32(s.Network), r) sig := acc.SignHashable(s.Network, r)
incRoot := s.getIncompleteRoot(r.Index, myIndex) incRoot := s.getIncompleteRoot(r.Index, myIndex)
incRoot.Lock() incRoot.Lock()
defer incRoot.Unlock() defer incRoot.Unlock()
@ -116,7 +116,7 @@ func (s *service) signAndSend(r *state.MPTRoot) error {
VerificationScript: acc.GetVerificationScript(), VerificationScript: acc.GetVerificationScript(),
}, },
} }
sig = acc.PrivateKey().SignHashable(uint32(s.Network), e) sig = acc.SignHashable(s.Network, e)
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
emit.Bytes(buf.BinWriter, sig) emit.Bytes(buf.BinWriter, sig)
e.Witness.InvocationScript = buf.Bytes() e.Witness.InvocationScript = buf.Bytes()

View file

@ -126,6 +126,15 @@ func (a *Account) SignTx(net netmode.Magic, t *transaction.Transaction) error {
return nil return nil
} }
// SignHashable signs the given Hashable item and returns the signature. If this
// account can't sign (CanSign() returns false) nil is returned.
func (a *Account) SignHashable(net netmode.Magic, item hash.Hashable) []byte {
if !a.CanSign() {
return nil
}
return a.privateKey.SignHashable(uint32(net), item)
}
// CanSign returns true when account is not locked and has a decrypted private // CanSign returns true when account is not locked and has a decrypted private
// key inside, so it's ready to create real signatures. // key inside, so it's ready to create real signatures.
func (a *Account) CanSign() bool { func (a *Account) CanSign() bool {

View file

@ -140,8 +140,9 @@ func TestContractSignTx(t *testing.T) {
acc2.Locked = true acc2.Locked = true
require.False(t, acc2.CanSign()) require.False(t, acc2.CanSign())
require.Error(t, acc2.SignTx(0, tx)) // Locked account. require.Error(t, acc2.SignTx(0, tx)) // Locked account.
require.Nil(t, acc2.PublicKey()) // Locked account. require.Nil(t, acc2.PublicKey()) // Locked account.
require.Nil(t, acc2.SignHashable(0, tx)) // Locked account.
acc2.Locked = false acc2.Locked = false
acc2.Close() acc2.Close()
@ -155,6 +156,7 @@ func TestContractSignTx(t *testing.T) {
}) })
require.NoError(t, acc.SignTx(0, tx)) // Add invocation script for existing witness. require.NoError(t, acc.SignTx(0, tx)) // Add invocation script for existing witness.
require.Equal(t, 66, len(tx.Scripts[1].InvocationScript)) require.Equal(t, 66, len(tx.Scripts[1].InvocationScript))
require.NotNil(t, acc.SignHashable(0, tx)) // Works via Hashable too.
require.NoError(t, multiAcc.SignTx(0, tx)) require.NoError(t, multiAcc.SignTx(0, tx))
require.Equal(t, 3, len(tx.Scripts)) require.Equal(t, 3, len(tx.Scripts))