cli/wallet: allow to cosign with a contract
Contracts have empty verification script and their hash is calculated differently.
This commit is contained in:
parent
8a4b97171a
commit
106c27782e
4 changed files with 28 additions and 14 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
"io/ioutil"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
@ -22,7 +23,11 @@ func InitAndSave(tx *transaction.Transaction, acc *wallet.Account, filename stri
|
|||
pub := priv.PublicKey()
|
||||
sign := priv.Sign(tx.GetSignedPart())
|
||||
scCtx := context.NewParameterContext("Neo.Core.ContractTransaction", tx)
|
||||
if err := scCtx.AddSignature(acc.Contract, pub, sign); err != nil {
|
||||
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 {
|
||||
return fmt.Errorf("can't add signature: %w", err)
|
||||
}
|
||||
return Save(scCtx, filename)
|
||||
|
|
|
@ -36,9 +36,13 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
return cli.NewExitError("verifiable item is not a transaction", 1)
|
||||
}
|
||||
|
||||
ch, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("wallet contains invalid account: %s", acc.Address), 1)
|
||||
}
|
||||
signerFound := false
|
||||
for i := range tx.Signers {
|
||||
if tx.Signers[i].Account == acc.Contract.ScriptHash() {
|
||||
if tx.Signers[i].Account == ch {
|
||||
signerFound = true
|
||||
break
|
||||
}
|
||||
|
@ -49,7 +53,7 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
|
||||
priv := acc.PrivateKey()
|
||||
sign := priv.Sign(tx.GetSignedPart())
|
||||
if err := c.AddSignature(acc.Contract, priv.PublicKey(), sign); err != nil {
|
||||
if err := c.AddSignature(ch, acc.Contract, priv.PublicKey(), sign); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't add signature: %w", err), 1)
|
||||
}
|
||||
if out := ctx.String("out"); out != "" {
|
||||
|
|
|
@ -72,8 +72,8 @@ func (c *ParameterContext) GetWitness(h util.Uint160) (*transaction.Witness, err
|
|||
}
|
||||
|
||||
// AddSignature adds a signature for the specified contract and public key.
|
||||
func (c *ParameterContext) AddSignature(ctr *wallet.Contract, pub *keys.PublicKey, sig []byte) error {
|
||||
item := c.getItemForContract(ctr.ScriptHash(), ctr)
|
||||
func (c *ParameterContext) AddSignature(h util.Uint160, ctr *wallet.Contract, pub *keys.PublicKey, sig []byte) error {
|
||||
item := c.getItemForContract(h, ctr)
|
||||
if _, pubs, ok := vm.ParseMultiSigContract(ctr.Script); ok {
|
||||
if item.GetSignature(pub) != nil {
|
||||
return errors.New("signature is already added")
|
||||
|
@ -121,10 +121,11 @@ func (c *ParameterContext) AddSignature(ctr *wallet.Contract, pub *keys.PublicKe
|
|||
index = i
|
||||
}
|
||||
}
|
||||
if index == -1 {
|
||||
if index != -1 {
|
||||
item.Parameters[index].Value = sig
|
||||
} else if !ctr.Deployed {
|
||||
return errors.New("missing signature parameter")
|
||||
}
|
||||
item.Parameters[index].Value = sig
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -137,8 +138,12 @@ func (c *ParameterContext) getItemForContract(h util.Uint160, ctr *wallet.Contra
|
|||
for i := range params {
|
||||
params[i].Type = ctr.Parameters[i].Type
|
||||
}
|
||||
script := ctr.Script
|
||||
if ctr.Deployed {
|
||||
script = nil
|
||||
}
|
||||
item = &Item{
|
||||
Script: ctr.Script,
|
||||
Script: script,
|
||||
Parameters: params,
|
||||
Signatures: make(map[string][]byte),
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@ func TestParameterContext_AddSignatureSimpleContract(t *testing.T) {
|
|||
newParam(smartcontract.SignatureType, "parameter1"),
|
||||
},
|
||||
}
|
||||
require.Error(t, c.AddSignature(ctr, pub, sig))
|
||||
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pub, sig))
|
||||
if item := c.Items[ctr.ScriptHash()]; item != nil {
|
||||
require.Nil(t, item.Parameters[0].Value)
|
||||
}
|
||||
|
||||
ctr.Parameters = ctr.Parameters[:0]
|
||||
require.Error(t, c.AddSignature(ctr, pub, sig))
|
||||
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pub, sig))
|
||||
if item := c.Items[ctr.ScriptHash()]; item != nil {
|
||||
require.Nil(t, item.Parameters[0].Value)
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func TestParameterContext_AddSignatureSimpleContract(t *testing.T) {
|
|||
Script: pub.GetVerificationScript(),
|
||||
Parameters: []wallet.ContractParam{newParam(smartcontract.SignatureType, "parameter0")},
|
||||
}
|
||||
require.NoError(t, c.AddSignature(ctr, pub, sig))
|
||||
require.NoError(t, c.AddSignature(ctr.ScriptHash(), ctr, pub, sig))
|
||||
item := c.Items[ctr.ScriptHash()]
|
||||
require.NotNil(t, item)
|
||||
require.Equal(t, sig, item.Parameters[0].Value)
|
||||
|
@ -95,13 +95,13 @@ func TestParameterContext_AddSignatureMultisig(t *testing.T) {
|
|||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
sig := priv.Sign(data)
|
||||
require.Error(t, c.AddSignature(ctr, priv.PublicKey(), sig))
|
||||
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, priv.PublicKey(), sig))
|
||||
|
||||
indices := []int{2, 3, 0} // random order
|
||||
for _, i := range indices {
|
||||
sig := privs[i].Sign(data)
|
||||
require.NoError(t, c.AddSignature(ctr, pubs[i], sig))
|
||||
require.Error(t, c.AddSignature(ctr, pubs[i], sig))
|
||||
require.NoError(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig))
|
||||
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig))
|
||||
|
||||
item := c.Items[ctr.ScriptHash()]
|
||||
require.NotNil(t, item)
|
||||
|
|
Loading…
Reference in a new issue