From e164625a7ff43a5c322333f34ea7856719de070c Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 1 Sep 2022 20:42:42 +0300 Subject: [PATCH] wallet: provide (*Account).SignHashable API Make PrivateKey() less used and less useful. --- cli/paramcontext/context.go | 6 ++---- cli/wallet/multisig.go | 3 +-- pkg/neotest/signer.go | 4 ++-- pkg/rpcclient/notary/actor.go | 2 +- pkg/rpcclient/rpc.go | 2 +- pkg/services/notary/notary.go | 2 +- pkg/services/stateroot/network.go | 2 +- pkg/services/stateroot/validators.go | 4 ++-- pkg/wallet/account.go | 9 +++++++++ pkg/wallet/account_test.go | 6 ++++-- 10 files changed, 24 insertions(+), 16 deletions(-) diff --git a/cli/paramcontext/context.go b/cli/paramcontext/context.go index bd1b8d5d9..d8fe06999 100644 --- a/cli/paramcontext/context.go +++ b/cli/paramcontext/context.go @@ -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) } } diff --git a/cli/wallet/multisig.go b/cli/wallet/multisig.go index e489a42ef..8b691fd43 100644 --- a/cli/wallet/multisig.go +++ b/cli/wallet/multisig.go @@ -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) } diff --git a/pkg/neotest/signer.go b/pkg/neotest/signer.go index 5821e4803..df529e607 100644 --- a/pkg/neotest/signer.go +++ b/pkg/neotest/signer.go @@ -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...) } diff --git a/pkg/rpcclient/notary/actor.go b/pkg/rpcclient/notary/actor.go index b115c9b74..06c9ef958 100644 --- a/pkg/rpcclient/notary/actor.go +++ b/pkg/rpcclient/notary/actor.go @@ -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) diff --git a/pkg/rpcclient/rpc.go b/pkg/rpcclient/rpc.go index cacbc4ea9..e1cd3b52c 100644 --- a/pkg/rpcclient/rpc.go +++ b/pkg/rpcclient/rpc.go @@ -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) diff --git a/pkg/services/notary/notary.go b/pkg/services/notary/notary.go index fa3f3dd3f..f496902e9 100644 --- a/pkg/services/notary/notary.go +++ b/pkg/services/notary/notary.go @@ -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 { diff --git a/pkg/services/stateroot/network.go b/pkg/services/stateroot/network.go index e91fb5100..cb586e2c0 100644 --- a/pkg/services/stateroot/network.go +++ b/pkg/services/stateroot/network.go @@ -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() diff --git a/pkg/services/stateroot/validators.go b/pkg/services/stateroot/validators.go index 9bfe6e741..fc1bd1db1 100644 --- a/pkg/services/stateroot/validators.go +++ b/pkg/services/stateroot/validators.go @@ -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() diff --git a/pkg/wallet/account.go b/pkg/wallet/account.go index bd436d6ab..2f5cb59f6 100644 --- a/pkg/wallet/account.go +++ b/pkg/wallet/account.go @@ -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 { diff --git a/pkg/wallet/account_test.go b/pkg/wallet/account_test.go index 714aa227e..a96340967 100644 --- a/pkg/wallet/account_test.go +++ b/pkg/wallet/account_test.go @@ -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))