From c8ff44560e5e4ecd596239d5a07063a4a134cb28 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 8 Dec 2023 15:38:54 +0300 Subject: [PATCH] neotest: reuse wallet.Account for contract signers Refs #3245 Refs #3233 Signed-off-by: Evgenii Stratonikov --- pkg/neotest/basic.go | 5 +-- pkg/neotest/signer.go | 79 +++++++++++++++---------------------------- 2 files changed, 30 insertions(+), 54 deletions(-) diff --git a/pkg/neotest/basic.go b/pkg/neotest/basic.go index c64a6b4a2..c789d7ae6 100644 --- a/pkg/neotest/basic.go +++ b/pkg/neotest/basic.go @@ -301,8 +301,9 @@ func AddNetworkFee(t testing.TB, bc *core.Blockchain, tx *transaction.Transactio baseFee := bc.GetBaseExecFee() size := io.GetVarSize(tx) for _, sgr := range signers { - if csgr, ok := sgr.(ContractSigner); ok { - sc, err := csgr.InvocationScript(tx) + csgr, ok := sgr.(SingleSigner) + if ok && csgr.Account().Contract.InvocationBuilder != nil { + sc, err := csgr.Account().Contract.InvocationBuilder(tx) require.NoError(t, err) txCopy := *tx diff --git a/pkg/neotest/signer.go b/pkg/neotest/signer.go index 8446e177f..a8793cc6a 100644 --- a/pkg/neotest/signer.go +++ b/pkg/neotest/signer.go @@ -2,7 +2,6 @@ package neotest import ( "bytes" - "errors" "fmt" "sort" "testing" @@ -11,6 +10,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/io" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" @@ -47,13 +47,6 @@ type MultiSigner interface { Single(n int) SingleSigner } -// ContractSigner is an interface for contract signer. -type ContractSigner interface { - Signer - // InvocationScript returns an invocation script to be used as invocation script for contract-based witness. - InvocationScript(tx *transaction.Transaction) ([]byte, error) -} - // signer represents a simple-signature signer. type signer wallet.Account @@ -190,33 +183,30 @@ func checkMultiSigner(t testing.TB, s Signer) { } } -type contractSigner struct { - params func(tx *transaction.Transaction) []any - scriptHash util.Uint160 -} +type contractSigner wallet.Account // NewContractSigner returns a contract signer for the provided contract hash. // getInvParams must return params to be used as invocation script for contract-based witness. -func NewContractSigner(h util.Uint160, getInvParams func(tx *transaction.Transaction) []any) ContractSigner { +func NewContractSigner(h util.Uint160, getInvParams func(tx *transaction.Transaction) []any) SingleSigner { return &contractSigner{ - scriptHash: h, - params: getInvParams, + Address: address.Uint160ToString(h), + Contract: &wallet.Contract{ + Deployed: true, + InvocationBuilder: func(tx *transaction.Transaction) ([]byte, error) { + params := getInvParams(tx) + script := io.NewBufBinWriter() + for i := range params { + emit.Any(script.BinWriter, params[i]) + } + if script.Err != nil { + return nil, script.Err + } + return script.Bytes(), nil + }, + }, } } -// InvocationScript implements ContractSigner. -func (s *contractSigner) InvocationScript(tx *transaction.Transaction) ([]byte, error) { - params := s.params(tx) - script := io.NewBufBinWriter() - for i := range params { - emit.Any(script.BinWriter, params[i]) - } - if script.Err != nil { - return nil, script.Err - } - return script.Bytes(), nil -} - // Script implements ContractSigner. func (s *contractSigner) Script() []byte { return []byte{} @@ -224,7 +214,12 @@ func (s *contractSigner) Script() []byte { // ScriptHash implements ContractSigner. func (s *contractSigner) ScriptHash() util.Uint160 { - return s.scriptHash + return s.Account().ScriptHash() +} + +// ScriptHash implements ContractSigner. +func (s *contractSigner) Account() *wallet.Account { + return (*wallet.Account)(s) } // SignHashable implements ContractSigner. @@ -234,27 +229,7 @@ func (s *contractSigner) SignHashable(uint32, hash.Hashable) []byte { // SignTx implements ContractSigner. func (s *contractSigner) SignTx(magic netmode.Magic, tx *transaction.Transaction) error { - pos := -1 - for idx := range tx.Signers { - if tx.Signers[idx].Account.Equals(s.ScriptHash()) { - pos = idx - break - } - } - if pos < 0 { - return fmt.Errorf("signer %s not found", s.ScriptHash().String()) - } - if len(tx.Scripts) < pos { - return errors.New("transaction is not yet signed by the previous signer") - } - invoc, err := s.InvocationScript(tx) - if err != nil { - return err - } - if len(tx.Scripts) == pos { - tx.Scripts = append(tx.Scripts, transaction.Witness{}) - } - tx.Scripts[pos].InvocationScript = invoc - tx.Scripts[pos].VerificationScript = s.Script() - return nil + // Here we rely on `len(s.Contract.Parameters) == 0` being after the `s.Contract.InvocationBuilder != nil` check, + // because we cannot determine the list of parameters unless we already have tx. + return s.Account().SignTx(magic, tx) }