core: fix CalculateNetworkFee for signature contracts

First PUSHDATA1 is from invocation script, the second PUSHDATA1 is
from verification script. E.g.:

Invocation script:

INDEX    OPCODE       PARAMETER
0        PUSHDATA1    035913b9588da23a5c3ce14b2886a6b8ebb6a0eb92bdaa948510dfb5ae5194d6cb    <<
35       PUSHNULL
36       SYSCALL      Neo.Crypto.VerifyWithECDsaSecp256r1 (95440d78)

Verification script:

INDEX    OPCODE       PARAMETER
0        PUSHDATA1    3930fe5a9b44682f37741955df4a5f2585ed5aa438fa6e17ae51083673b1d64253e5a859c0cf168be67971e53a23c1c40582777d94a8e391db23ff613849627d    <<
This commit is contained in:
Anna Shaleva 2020-09-30 13:20:40 +03:00
parent 230352d99f
commit 2b11e99225
2 changed files with 44 additions and 7 deletions

View file

@ -215,7 +215,7 @@ func TestVerifyTx(t *testing.T) {
bc := newTestChain(t) bc := newTestChain(t)
defer bc.Close() defer bc.Close()
accs := make([]*wallet.Account, 4) accs := make([]*wallet.Account, 5)
for i := range accs { for i := range accs {
var err error var err error
accs[i], err = wallet.NewAccount() accs[i], err = wallet.NewAccount()
@ -291,12 +291,49 @@ func TestVerifyTx(t *testing.T) {
require.NoError(t, accs[0].SignTx(tx)) require.NoError(t, accs[0].SignTx(tx))
checkErr(t, ErrTxTooBig, tx) checkErr(t, ErrTxTooBig, tx)
}) })
t.Run("NetworkFee", func(t *testing.T) {
t.Run("SmallNetworkFee", func(t *testing.T) { t.Run("SmallNetworkFee", func(t *testing.T) {
tx := bc.newTestTx(h, testScript) tx := bc.newTestTx(h, testScript)
tx.NetworkFee = 1 tx.NetworkFee = 1
require.NoError(t, accs[0].SignTx(tx)) require.NoError(t, accs[0].SignTx(tx))
checkErr(t, ErrTxSmallNetworkFee, tx) checkErr(t, ErrTxSmallNetworkFee, tx)
}) })
t.Run("CalculateNetworkFee, signature script", func(t *testing.T) {
tx := bc.newTestTx(h, testScript)
expectedSize := io.GetVarSize(tx)
verificationNetFee, calculatedScriptSize := CalculateNetworkFee(accs[0].Contract.Script)
expectedSize += calculatedScriptSize
expectedNetFee := verificationNetFee + int64(expectedSize)*bc.FeePerByte()
tx.NetworkFee = expectedNetFee
require.NoError(t, accs[0].SignTx(tx))
actualSize := io.GetVarSize(tx)
require.Equal(t, expectedSize, actualSize)
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, tx)
gasConsumed, err := bc.verifyHashAgainstScript(h, &tx.Scripts[0], interopCtx, -1)
require.NoError(t, err)
require.Equal(t, verificationNetFee, gasConsumed)
require.Equal(t, expectedNetFee, bc.FeePerByte()*int64(actualSize)+gasConsumed)
})
t.Run("CalculateNetworkFee, multisignature script", func(t *testing.T) {
multisigAcc := accs[4]
pKeys := keys.PublicKeys{multisigAcc.PrivateKey().PublicKey()}
require.NoError(t, multisigAcc.ConvertMultisig(1, pKeys))
multisigHash := hash.Hash160(multisigAcc.Contract.Script)
tx := bc.newTestTx(multisigHash, testScript)
verificationNetFee, calculatedScriptSize := CalculateNetworkFee(multisigAcc.Contract.Script)
expectedSize := io.GetVarSize(tx) + calculatedScriptSize
expectedNetFee := verificationNetFee + int64(expectedSize)*bc.FeePerByte()
tx.NetworkFee = expectedNetFee
require.NoError(t, multisigAcc.SignTx(tx))
actualSize := io.GetVarSize(tx)
require.Equal(t, expectedSize, actualSize)
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, tx)
gasConsumed, err := bc.verifyHashAgainstScript(multisigHash, &tx.Scripts[0], interopCtx, -1)
require.NoError(t, err)
require.Equal(t, verificationNetFee, gasConsumed)
require.Equal(t, expectedNetFee, bc.FeePerByte()*int64(actualSize)+gasConsumed)
})
})
t.Run("Conflict", func(t *testing.T) { t.Run("Conflict", func(t *testing.T) {
balance := bc.GetUtilityTokenBalance(h).Int64() balance := bc.GetUtilityTokenBalance(h).Int64()
tx := bc.newTestTx(h, testScript) tx := bc.newTestTx(h, testScript)

View file

@ -138,7 +138,7 @@ func CalculateNetworkFee(script []byte) (int64, int) {
) )
if vm.IsSignatureContract(script) { if vm.IsSignatureContract(script) {
size += 67 + io.GetVarSize(script) size += 67 + io.GetVarSize(script)
netFee += opcodePrice(opcode.PUSHDATA1, opcode.PUSHNULL) + crypto.ECDSAVerifyPrice netFee += opcodePrice(opcode.PUSHDATA1, opcode.PUSHNULL, opcode.PUSHDATA1) + crypto.ECDSAVerifyPrice
} else if m, pubs, ok := vm.ParseMultiSigContract(script); ok { } else if m, pubs, ok := vm.ParseMultiSigContract(script); ok {
n := len(pubs) n := len(pubs)
sizeInv := 66 * m sizeInv := 66 * m