forked from TrueCloudLab/neoneo-go
wallet: add ScriptHash() to Account
It allows to simplify a lot of code and avoid getting a PrivateKey in some cases.
This commit is contained in:
parent
fd8da6fdb9
commit
e569edc841
16 changed files with 38 additions and 74 deletions
|
@ -199,10 +199,7 @@ func ParseParams(args []string, calledFromMain bool) (int, []smartcontract.Param
|
|||
// accounts from the provided wallet.
|
||||
func GetSignersAccounts(senderAcc *wallet.Account, wall *wallet.Wallet, signers []transaction.Signer, accScope transaction.WitnessScope) ([]actor.SignerAccount, error) {
|
||||
signersAccounts := make([]actor.SignerAccount, 0, len(signers)+1)
|
||||
sender, err := address.StringToUint160(senderAcc.Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sender := senderAcc.ScriptHash()
|
||||
signersAccounts = append(signersAccounts, actor.SignerAccount{
|
||||
Signer: transaction.Signer{
|
||||
Account: sender,
|
||||
|
|
|
@ -162,8 +162,7 @@ func TestNEP17Transfer(t *testing.T) {
|
|||
e.checkNextLine(t, `^Total fee:\s*(\d|\.)+`)
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
sh, err := address.StringToUint160(w.Accounts[0].Address)
|
||||
require.NoError(t, err)
|
||||
sh := w.Accounts[0].ScriptHash()
|
||||
b, _ := e.Chain.GetGoverningTokenBalance(sh)
|
||||
require.Equal(t, big.NewInt(1), b)
|
||||
|
||||
|
@ -172,8 +171,6 @@ func TestNEP17Transfer(t *testing.T) {
|
|||
e.Run(t, append(args, "--force")...)
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
sh, err := address.StringToUint160(w.Accounts[0].Address)
|
||||
require.NoError(t, err)
|
||||
b, _ := e.Chain.GetGoverningTokenBalance(sh)
|
||||
require.Equal(t, big.NewInt(2), b)
|
||||
})
|
||||
|
@ -198,8 +195,6 @@ func TestNEP17Transfer(t *testing.T) {
|
|||
e.Run(t, args...)
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
sh, err := address.StringToUint160(w.Accounts[0].Address)
|
||||
require.NoError(t, err)
|
||||
b, _ := e.Chain.GetGoverningTokenBalance(sh)
|
||||
require.Equal(t, big.NewInt(3), b)
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/context"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
)
|
||||
|
@ -21,11 +20,7 @@ func InitAndSave(net netmode.Magic, tx *transaction.Transaction, acc *wallet.Acc
|
|||
priv := acc.PrivateKey()
|
||||
pub := priv.PublicKey()
|
||||
sign := priv.SignHashable(uint32(net), tx)
|
||||
h, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid address: %s", acc.Address)
|
||||
}
|
||||
if err := scCtx.AddSignature(h, acc.Contract, pub, sign); err != nil {
|
||||
if err := scCtx.AddSignature(acc.ScriptHash(), acc.Contract, pub, sign); err != nil {
|
||||
return fmt.Errorf("can't add signature: %w", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,17 +286,12 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
}
|
||||
}
|
||||
for k, acc := range accounts {
|
||||
addrHash, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid account address: %w", err), 1)
|
||||
}
|
||||
|
||||
if k != 0 {
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "Account %s\n", acc.Address)
|
||||
|
||||
err = accHandler(ctx, c, addrHash, name, token, tokenID)
|
||||
err = accHandler(ctx, c, acc.ScriptHash(), name, token, tokenID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ func TestNEO_Vote(t *testing.T) {
|
|||
txes = append(txes, voteTx)
|
||||
}
|
||||
}
|
||||
txes = append(txes, policyInvoker.PrepareInvoke(t, "blockAccount", candidates[len(candidates)-1].(neotest.SingleSigner).Account().PublicKey().GetScriptHash()))
|
||||
txes = append(txes, policyInvoker.PrepareInvoke(t, "blockAccount", candidates[len(candidates)-1].(neotest.SingleSigner).Account().ScriptHash()))
|
||||
neoValidatorsInvoker.AddNewBlock(t, txes...)
|
||||
for _, tx := range txes {
|
||||
e.CheckHalt(t, tx.Hash(), stackitem.Make(true)) // luckily, both `transfer`, `registerCandidate` and `vote` return boolean values
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -276,8 +275,5 @@ func TestSender(t *testing.T) {
|
|||
client, acc := testRPCAndAccount(t)
|
||||
a, err := NewSimple(client, acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
addr, err := address.StringToUint160(acc.Address)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, addr, a.Sender())
|
||||
require.Equal(t, acc.ScriptHash(), a.Sender())
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
@ -88,13 +87,9 @@ func (c *Client) CreateNEP11TransferTx(acc *wallet.Account, tokenHash util.Uint1
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create NEP-11 transfer script: %w", err)
|
||||
}
|
||||
from, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad account address: %w", err)
|
||||
}
|
||||
return c.CreateTxFromScript(script, acc, -1, gas, append([]SignerAccount{{
|
||||
Signer: transaction.Signer{
|
||||
Account: from,
|
||||
Account: acc.ScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
Account: acc,
|
||||
|
@ -148,11 +143,7 @@ func (c *Client) NEP11NDOwnerOf(tokenHash util.Uint160, tokenID []byte) (util.Ui
|
|||
// versions.
|
||||
func (c *Client) TransferNEP11D(acc *wallet.Account, to util.Uint160,
|
||||
tokenHash util.Uint160, amount int64, tokenID []byte, data interface{}, gas int64, cosigners []SignerAccount) (util.Uint256, error) {
|
||||
from, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return util.Uint256{}, fmt.Errorf("bad account address: %w", err)
|
||||
}
|
||||
tx, err := c.CreateNEP11TransferTx(acc, tokenHash, gas, cosigners, from, to, amount, tokenID, data)
|
||||
tx, err := c.CreateNEP11TransferTx(acc, tokenHash, gas, cosigners, acc.ScriptHash(), to, amount, tokenID, data)
|
||||
if err != nil {
|
||||
return util.Uint256{}, err
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -96,10 +95,7 @@ func (c *Client) CreateNEP17TransferTx(acc *wallet.Account, to util.Uint160,
|
|||
// be removed in future versions.
|
||||
func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64,
|
||||
recipients []TransferTarget, cosigners []SignerAccount) (*transaction.Transaction, error) {
|
||||
from, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad account address: %w", err)
|
||||
}
|
||||
from := acc.ScriptHash()
|
||||
b := smartcontract.NewBuilder()
|
||||
for i := range recipients {
|
||||
b.InvokeWithAssert(recipients[i].Token, "transfer",
|
||||
|
|
|
@ -827,10 +827,7 @@ func getSigners(sender *wallet.Account, cosigners []SignerAccount) ([]transactio
|
|||
signers []transaction.Signer
|
||||
accounts []*wallet.Account
|
||||
)
|
||||
from, err := address.StringToUint160(sender.Address)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("bad sender account address: %v", err)
|
||||
}
|
||||
from := sender.ScriptHash()
|
||||
s := transaction.Signer{
|
||||
Account: from,
|
||||
Scopes: transaction.None,
|
||||
|
@ -875,10 +872,7 @@ func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fa
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get native Notary hash: %w", err)
|
||||
}
|
||||
from, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad account address: %v", err)
|
||||
}
|
||||
from := acc.ScriptHash()
|
||||
signers := []transaction.Signer{{Account: notaryHash}, {Account: from}}
|
||||
if fallbackSysFee < 0 {
|
||||
result, err := c.InvokeScript(fallbackScript, signers)
|
||||
|
|
|
@ -175,7 +175,7 @@ func TestNotary(t *testing.T) {
|
|||
Scopes: transaction.None,
|
||||
},
|
||||
{
|
||||
Account: requester.PublicKey().GetScriptHash(),
|
||||
Account: requester.ScriptHash(),
|
||||
Scopes: transaction.None,
|
||||
},
|
||||
}
|
||||
|
@ -721,9 +721,9 @@ func TestNotary(t *testing.T) {
|
|||
requester1, _ := wallet.NewAccount()
|
||||
requester2, _ := wallet.NewAccount()
|
||||
amount := int64(100_0000_0000)
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []interface{}{requester1.PublicKey().GetScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []interface{}{requester1.ScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
e.CheckGASBalance(t, notaryHash, big.NewInt(amount))
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []interface{}{requester2.PublicKey().GetScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []interface{}{requester2.ScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
e.CheckGASBalance(t, notaryHash, big.NewInt(2*amount))
|
||||
|
||||
// create request for 2 standard signatures => main tx should be completed after the second request is added to the pool
|
||||
|
|
|
@ -1033,11 +1033,6 @@ func TestSignAndPushP2PNotaryRequest(t *testing.T) {
|
|||
})
|
||||
|
||||
require.NoError(t, c.Init())
|
||||
t.Run("bad account address", func(t *testing.T) {
|
||||
_, err := c.SignAndPushP2PNotaryRequest(nil, nil, 0, 0, 0, &wallet.Account{Address: "not-an-addr"}) //nolint:staticcheck // SA1019: c.SignAndPushP2PNotaryRequest is deprecated
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("bad fallback script", func(t *testing.T) {
|
||||
_, err := c.SignAndPushP2PNotaryRequest(nil, []byte{byte(opcode.ASSERT)}, -1, 0, 0, acc) //nolint:staticcheck // SA1019: c.SignAndPushP2PNotaryRequest is deprecated
|
||||
require.NotNil(t, err)
|
||||
|
|
|
@ -90,7 +90,6 @@ func (s *service) trySendRoot(ir *incompleteRoot, acc *wallet.Account) {
|
|||
}
|
||||
|
||||
func (s *service) sendValidatedRoot(r *state.MPTRoot, acc *wallet.Account) {
|
||||
priv := acc.PrivateKey()
|
||||
w := io.NewBufBinWriter()
|
||||
m := NewMessage(RootT, r)
|
||||
m.EncodeBinary(w.BinWriter)
|
||||
|
@ -98,13 +97,13 @@ func (s *service) sendValidatedRoot(r *state.MPTRoot, acc *wallet.Account) {
|
|||
Category: Category,
|
||||
ValidBlockStart: r.Index,
|
||||
ValidBlockEnd: r.Index + rootValidEndInc,
|
||||
Sender: priv.GetScriptHash(),
|
||||
Sender: acc.ScriptHash(),
|
||||
Data: w.Bytes(),
|
||||
Witness: transaction.Witness{
|
||||
VerificationScript: acc.GetVerificationScript(),
|
||||
},
|
||||
}
|
||||
sig := priv.SignHashable(uint32(s.Network), ep)
|
||||
sig := acc.PrivateKey().SignHashable(uint32(s.Network), ep)
|
||||
buf := io.NewBufBinWriter()
|
||||
emit.Bytes(buf.BinWriter, sig)
|
||||
ep.Witness.InvocationScript = buf.Bytes()
|
||||
|
|
|
@ -110,7 +110,7 @@ func (s *service) signAndSend(r *state.MPTRoot) error {
|
|||
Category: Category,
|
||||
ValidBlockStart: r.Index,
|
||||
ValidBlockEnd: r.Index + voteValidEndInc,
|
||||
Sender: acc.PrivateKey().GetScriptHash(),
|
||||
Sender: acc.ScriptHash(),
|
||||
Data: w.Bytes(),
|
||||
Witness: transaction.Witness{
|
||||
VerificationScript: acc.GetVerificationScript(),
|
||||
|
|
|
@ -20,6 +20,9 @@ type Account struct {
|
|||
// NEO private key.
|
||||
privateKey *keys.PrivateKey
|
||||
|
||||
// Script hash corresponding to the Address.
|
||||
scriptHash util.Uint160
|
||||
|
||||
// NEO public address.
|
||||
Address string `json:"address"`
|
||||
|
||||
|
@ -80,8 +83,6 @@ func (a *Account) SignTx(net netmode.Magic, t *transaction.Transaction) error {
|
|||
var (
|
||||
haveAcc bool
|
||||
pos int
|
||||
accHash util.Uint160
|
||||
err error
|
||||
)
|
||||
if a.Locked {
|
||||
return errors.New("account is locked")
|
||||
|
@ -89,12 +90,8 @@ func (a *Account) SignTx(net netmode.Magic, t *transaction.Transaction) error {
|
|||
if a.Contract == nil {
|
||||
return errors.New("account has no contract")
|
||||
}
|
||||
accHash, err = address.StringToUint160(a.Address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range t.Signers {
|
||||
if t.Signers[i].Account.Equals(accHash) {
|
||||
if t.Signers[i].Account.Equals(a.ScriptHash()) {
|
||||
haveAcc = true
|
||||
pos = i
|
||||
break
|
||||
|
@ -184,6 +181,16 @@ func (a *Account) PublicKey() *keys.PublicKey {
|
|||
return a.privateKey.PublicKey()
|
||||
}
|
||||
|
||||
// ScriptHash returns the script hash (account) that the Account.Address is
|
||||
// derived from. It never returns an error, so if this Account has an invalid
|
||||
// Address you'll just get a zero script hash.
|
||||
func (a *Account) ScriptHash() util.Uint160 {
|
||||
if a.scriptHash.Equals(util.Uint160{}) {
|
||||
a.scriptHash, _ = address.StringToUint160(a.Address)
|
||||
}
|
||||
return a.scriptHash
|
||||
}
|
||||
|
||||
// Close cleans up the private key used by Account and disassociates it from
|
||||
// Account. The Account can no longer sign anything after this call, but Decrypt
|
||||
// can make it usable again.
|
||||
|
@ -243,7 +250,8 @@ func (a *Account) ConvertMultisig(m int, pubs []*keys.PublicKey) error {
|
|||
return err
|
||||
}
|
||||
|
||||
a.Address = address.Uint160ToString(hash.Hash160(script))
|
||||
a.scriptHash = hash.Hash160(script)
|
||||
a.Address = address.Uint160ToString(a.scriptHash)
|
||||
a.Contract = &Contract{
|
||||
Script: script,
|
||||
Parameters: getContractParams(m),
|
||||
|
@ -255,11 +263,11 @@ func (a *Account) ConvertMultisig(m int, pubs []*keys.PublicKey) error {
|
|||
// NewAccountFromPrivateKey creates a wallet from the given PrivateKey.
|
||||
func NewAccountFromPrivateKey(p *keys.PrivateKey) *Account {
|
||||
pubKey := p.PublicKey()
|
||||
pubAddr := p.Address()
|
||||
|
||||
a := &Account{
|
||||
privateKey: p,
|
||||
Address: pubAddr,
|
||||
scriptHash: p.GetScriptHash(),
|
||||
Address: p.Address(),
|
||||
Contract: &Contract{
|
||||
Script: pubKey.GetVerificationScript(),
|
||||
Parameters: getContractParams(1),
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -18,6 +19,7 @@ func TestNewAccount(t *testing.T) {
|
|||
acc, err := NewAccount()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, acc)
|
||||
require.Equal(t, acc.Address, address.Uint160ToString(acc.ScriptHash()))
|
||||
}
|
||||
|
||||
func TestDecryptAccount(t *testing.T) {
|
||||
|
|
|
@ -102,6 +102,7 @@ func TestSave(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(w2.Accounts))
|
||||
require.NoError(t, w2.Accounts[1].Decrypt("pass", w2.Scrypt))
|
||||
_ = w2.Accounts[1].ScriptHash() // openedWallet has it for acc 1.
|
||||
require.Equal(t, openedWallet.Accounts, w2.Accounts)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue