core: allow to sign with arbitrary signer

Related #1677.
This commit is contained in:
Evgeniy Stratonikov 2021-01-22 15:11:57 +03:00
parent 818d5988f5
commit ec6317d643

View file

@ -433,8 +433,10 @@ func addNetworkFee(bc *Blockchain, tx *transaction.Transaction, sender *wallet.A
return nil
}
// Signer can be either bool or *wallet.Account.
// In the first case `true` means sign by committee, `false` means sign by validators.
func prepareContractMethodInvokeGeneric(chain *Blockchain, sysfee int64,
hash util.Uint160, method string, isCommittee bool, args ...interface{}) (*transaction.Transaction, error) {
hash util.Uint160, method string, signer interface{}, args ...interface{}) (*transaction.Transaction, error) {
w := io.NewBufBinWriter()
emit.AppCall(w.BinWriter, hash, method, callflag.All, args...)
if w.Err != nil {
@ -444,12 +446,21 @@ func prepareContractMethodInvokeGeneric(chain *Blockchain, sysfee int64,
tx := transaction.New(chain.GetConfig().Magic, script, sysfee)
tx.ValidUntilBlock = chain.blockHeight + 1
var err error
if isCommittee {
addSigners(testchain.CommitteeScriptHash(), tx)
err = testchain.SignTxCommittee(chain, tx)
} else {
addSigners(neoOwner, tx)
err = testchain.SignTx(chain, tx)
switch s := signer.(type) {
case bool:
if s {
addSigners(testchain.CommitteeScriptHash(), tx)
err = testchain.SignTxCommittee(chain, tx)
} else {
addSigners(neoOwner, tx)
err = testchain.SignTx(chain, tx)
}
case *wallet.Account:
signTxWithAccounts(chain, tx, s)
case []*wallet.Account:
signTxWithAccounts(chain, tx, s...)
default:
panic("invalid signer")
}
if err != nil {
return nil, err
@ -457,6 +468,30 @@ func prepareContractMethodInvokeGeneric(chain *Blockchain, sysfee int64,
return tx, nil
}
func signTxWithAccounts(chain *Blockchain, tx *transaction.Transaction, accs ...*wallet.Account) {
scope := transaction.CalledByEntry
for _, acc := range accs {
tx.Signers = append(tx.Signers, transaction.Signer{
Account: acc.PrivateKey().GetScriptHash(),
Scopes: scope,
})
scope = transaction.Global
}
size := io.GetVarSize(tx)
for _, acc := range accs {
netFee, sizeDelta := fee.Calculate(chain.GetBaseExecFee(), acc.Contract.Script)
size += sizeDelta
tx.NetworkFee += netFee
}
tx.NetworkFee += int64(size) * chain.FeePerByte()
for _, acc := range accs {
if err := acc.SignTx(tx); err != nil {
panic(err)
}
}
}
func prepareContractMethodInvoke(chain *Blockchain, sysfee int64,
hash util.Uint160, method string, args ...interface{}) (*transaction.Transaction, error) {
return prepareContractMethodInvokeGeneric(chain, sysfee, hash,
@ -486,9 +521,9 @@ func invokeContractMethod(chain *Blockchain, sysfee int64, hash util.Uint160, me
}
func invokeContractMethodGeneric(chain *Blockchain, sysfee int64, hash util.Uint160, method string,
isCommittee bool, args ...interface{}) (*state.AppExecResult, error) {
signer interface{}, args ...interface{}) (*state.AppExecResult, error) {
tx, err := prepareContractMethodInvokeGeneric(chain, sysfee, hash,
method, isCommittee, args...)
method, signer, args...)
if err != nil {
return nil, err
}
@ -509,26 +544,7 @@ func invokeContractMethodBy(t *testing.T, chain *Blockchain, signer *wallet.Acco
require.NoError(t, err)
require.Equal(t, vm.HaltState, res[0].VMState)
require.Equal(t, 0, len(res[0].Stack))
w := io.NewBufBinWriter()
emit.AppCall(w.BinWriter, hash, method, callflag.All, args...)
if w.Err != nil {
return nil, w.Err
}
script := w.Bytes()
tx := transaction.New(chain.GetConfig().Magic, script, sysfee)
tx.ValidUntilBlock = chain.blockHeight + 1
tx.Signers = []transaction.Signer{
{Account: signer.PrivateKey().PublicKey().GetScriptHash()},
}
tx.NetworkFee = netfee
err = signer.SignTx(tx)
require.NoError(t, err)
require.NoError(t, chain.AddBlock(chain.newBlock(tx)))
res, err = chain.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err)
return &res[0], nil
return invokeContractMethodGeneric(chain, sysfee, hash, method, signer, args...)
}
func transferTokenFromMultisigAccount(t *testing.T, chain *Blockchain, to, tokenHash util.Uint160, amount int64, additionalArgs ...interface{}) *transaction.Transaction {