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 {
scCtx := context.NewParameterContext("Neo.Network.P2P.Payloads.Transaction", net, tx)
if acc != nil && acc.CanSign() {
priv := acc.PrivateKey()
pub := priv.PublicKey()
sign := priv.SignHashable(uint32(net), tx)
if err := scCtx.AddSignature(acc.ScriptHash(), acc.Contract, pub, sign); err != nil {
sign := acc.SignHashable(net, tx)
if err := scCtx.AddSignature(acc.ScriptHash(), acc.Contract, acc.PublicKey(), sign); err != nil {
return fmt.Errorf("can't add signature: %w", err)
}
}

View file

@ -58,8 +58,7 @@ func signStoredTransaction(ctx *cli.Context) error {
}
if acc.CanSign() {
priv := acc.PrivateKey()
sign := priv.SignHashable(uint32(pc.Network), pc.Verifiable)
sign := acc.SignHashable(pc.Network, pc.Verifiable)
if err := pc.AddSignature(ch, acc.Contract, acc.PublicKey(), sign); err != nil {
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.
func (s *signer) SignHashable(magic uint32, item hash.Hashable) []byte {
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.
@ -130,7 +130,7 @@ func (m multiSigner) Script() []byte {
func (m multiSigner) SignHashable(magic uint32, item hash.Hashable) []byte {
var script []byte
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, sign...)
}

View file

@ -300,7 +300,7 @@ func (a *Actor) SendRequestExactly(mainTx *transaction.Transaction, fbTx *transa
FallbackTransaction: fbTx,
}
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(),
}
actualHash, err := a.rpc.SubmitP2PNotaryRequest(req)

View file

@ -938,7 +938,7 @@ func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fa
FallbackTransaction: fallbackTx,
}
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(),
}
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.
func (n *Notary) finalize(acc *wallet.Account, tx *transaction.Transaction, h util.Uint256) error {
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{},
}
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(),
},
}
sig := acc.PrivateKey().SignHashable(uint32(s.Network), ep)
sig := acc.SignHashable(s.Network, ep)
buf := io.NewBufBinWriter()
emit.Bytes(buf.BinWriter, sig)
ep.Witness.InvocationScript = buf.Bytes()

View file

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

View file

@ -126,6 +126,15 @@ func (a *Account) SignTx(net netmode.Magic, t *transaction.Transaction) error {
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
// key inside, so it's ready to create real signatures.
func (a *Account) CanSign() bool {

View file

@ -140,8 +140,9 @@ func TestContractSignTx(t *testing.T) {
acc2.Locked = true
require.False(t, acc2.CanSign())
require.Error(t, acc2.SignTx(0, tx)) // Locked account.
require.Nil(t, acc2.PublicKey()) // Locked account.
require.Error(t, acc2.SignTx(0, tx)) // Locked account.
require.Nil(t, acc2.PublicKey()) // Locked account.
require.Nil(t, acc2.SignHashable(0, tx)) // Locked account.
acc2.Locked = false
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.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.Equal(t, 3, len(tx.Scripts))