From d2a81daf576fa16f500ded87903dd51bf7f150f7 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 25 Mar 2021 11:38:15 +0300 Subject: [PATCH] rpc: refactor TestCalculateNetworkFee We need to ensure that we don't add extra network fee during calculation. --- pkg/rpc/server/client_test.go | 171 +++++++++++++++++++++++----------- 1 file changed, 118 insertions(+), 53 deletions(-) diff --git a/pkg/rpc/server/client_test.go b/pkg/rpc/server/client_test.go index 41305f332..4fb084ac4 100644 --- a/pkg/rpc/server/client_test.go +++ b/pkg/rpc/server/client_test.go @@ -71,6 +71,7 @@ func TestAddNetworkFee(t *testing.T) { defer chain.Close() defer rpcSrv.Shutdown() const extraFee = 10 + var nonce uint32 c, err := client.New(context.Background(), httpSrv.URL, client.Options{}) require.NoError(t, err) @@ -98,41 +99,105 @@ func TestAddNetworkFee(t *testing.T) { require.Error(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1])) }) t.Run("Simple", func(t *testing.T) { - tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - accs := getAccounts(t, 1) - tx.Signers = []transaction.Signer{{ - Account: accs[0].PrivateKey().GetScriptHash(), - Scopes: transaction.CalledByEntry, - }} - require.NoError(t, c.AddNetworkFee(tx, 10, accs[0])) - require.NoError(t, accs[0].SignTx(testchain.Network(), tx)) - cFee, _ := fee.Calculate(chain.GetBaseExecFee(), accs[0].Contract.Script) - require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+extraFee, tx.NetworkFee) + acc0 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0)) + check := func(t *testing.T, extraFee int64) { + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) + tx.ValidUntilBlock = 20 + tx.Signers = []transaction.Signer{{ + Account: acc0.PrivateKey().GetScriptHash(), + Scopes: transaction.CalledByEntry, + }} + tx.Nonce = nonce + nonce++ + + require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0)) + actual := tx.NetworkFee + + require.NoError(t, acc0.SignTx(testchain.Network(), tx)) + cFee, _ := fee.Calculate(chain.GetBaseExecFee(), acc0.Contract.Script) + expected := int64(io.GetVarSize(tx))*feePerByte + cFee + extraFee + + require.Equal(t, expected, actual) + err := chain.VerifyTx(tx) + if extraFee < 0 { + require.Error(t, err) + } else { + require.NoError(t, err) + } + } + + t.Run("with extra fee", func(t *testing.T) { + // check that calculated network fee with extra value is enough + check(t, extraFee) + }) + t.Run("without extra fee", func(t *testing.T) { + // check that calculated network fee without extra value is enough + check(t, 0) + }) + t.Run("exactFee-1", func(t *testing.T) { + // check that we don't add unexpected extra GAS + check(t, -1) + }) }) t.Run("Multi", func(t *testing.T) { - tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - accs := getAccounts(t, 4) - pubs := keys.PublicKeys{accs[1].PrivateKey().PublicKey(), accs[2].PrivateKey().PublicKey(), accs[3].PrivateKey().PublicKey()} - require.NoError(t, accs[1].ConvertMultisig(2, pubs)) - require.NoError(t, accs[2].ConvertMultisig(2, pubs)) - tx.Signers = []transaction.Signer{ - { - Account: accs[0].PrivateKey().GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - { - Account: hash.Hash160(accs[1].Contract.Script), - Scopes: transaction.Global, - }, + acc0 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0)) + acc1 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0)) + acc1.ConvertMultisig(3, keys.PublicKeys{ + testchain.PrivateKeyByID(0).PublicKey(), + testchain.PrivateKeyByID(1).PublicKey(), + testchain.PrivateKeyByID(2).PublicKey(), + testchain.PrivateKeyByID(3).PublicKey(), + }) + check := func(t *testing.T, extraFee int64) { + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) + tx.ValidUntilBlock = 20 + tx.Signers = []transaction.Signer{ + { + Account: acc0.PrivateKey().GetScriptHash(), + Scopes: transaction.CalledByEntry, + }, + { + Account: hash.Hash160(acc1.Contract.Script), + Scopes: transaction.Global, + }, + } + tx.Nonce = nonce + nonce++ + + require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1)) + actual := tx.NetworkFee + + require.NoError(t, acc0.SignTx(testchain.Network(), tx)) + tx.Scripts = append(tx.Scripts, transaction.Witness{ + InvocationScript: testchain.Sign(tx), + VerificationScript: acc1.Contract.Script, + }) + cFee, _ := fee.Calculate(chain.GetBaseExecFee(), acc0.Contract.Script) + cFeeM, _ := fee.Calculate(chain.GetBaseExecFee(), acc1.Contract.Script) + expected := int64(io.GetVarSize(tx))*feePerByte + cFee + cFeeM + extraFee + + require.Equal(t, expected, actual) + err := chain.VerifyTx(tx) + if extraFee < 0 { + require.Error(t, err) + } else { + require.NoError(t, err) + } } - require.NoError(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1])) - require.NoError(t, accs[0].SignTx(testchain.Network(), tx)) - require.NoError(t, accs[1].SignTx(testchain.Network(), tx)) - require.NoError(t, accs[2].SignTx(testchain.Network(), tx)) - cFee, _ := fee.Calculate(chain.GetBaseExecFee(), accs[0].Contract.Script) - cFeeM, _ := fee.Calculate(chain.GetBaseExecFee(), accs[1].Contract.Script) - require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+cFeeM+extraFee, tx.NetworkFee) + + t.Run("with extra fee", func(t *testing.T) { + // check that calculated network fee with extra value is enough + check(t, extraFee) + }) + t.Run("without extra fee", func(t *testing.T) { + // check that calculated network fee without extra value is enough + check(t, 0) + }) + t.Run("exactFee-1", func(t *testing.T) { + // check that we don't add unexpected extra GAS + check(t, -1) + }) }) t.Run("Contract", func(t *testing.T) { h, err := util.Uint160DecodeStringLE(verifyContractHash) @@ -142,16 +207,16 @@ func TestAddNetworkFee(t *testing.T) { acc1 := wallet.NewAccountFromPrivateKey(priv) // contract account acc1.Contract.Deployed = true acc1.Contract.Script, err = base64.StdEncoding.DecodeString(verifyContractAVM) + require.NoError(t, err) newTx := func(t *testing.T) *transaction.Transaction { tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - require.NoError(t, err) tx.ValidUntilBlock = chain.BlockHeight() + 10 return tx } t.Run("Valid", func(t *testing.T) { - completeTx := func(t *testing.T) *transaction.Transaction { + check := func(t *testing.T, extraFee int64) { tx := newTx(t) tx.Signers = []transaction.Signer{ { @@ -164,28 +229,28 @@ func TestAddNetworkFee(t *testing.T) { }, } require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1)) - return tx + require.NoError(t, acc0.SignTx(testchain.Network(), tx)) + tx.Scripts = append(tx.Scripts, transaction.Witness{}) + err = chain.VerifyTx(tx) + if extraFee < 0 { + require.Error(t, err) + } else { + require.NoError(t, err) + } } - // check that network fee with extra value is enough - tx1 := completeTx(t) - require.NoError(t, acc0.SignTx(testchain.Network(), tx1)) - tx1.Scripts = append(tx1.Scripts, transaction.Witness{}) - require.NoError(t, chain.VerifyTx(tx1)) - - // check that network fee without extra value is enough - tx2 := completeTx(t) - tx2.NetworkFee -= extraFee - require.NoError(t, acc0.SignTx(testchain.Network(), tx2)) - tx2.Scripts = append(tx2.Scripts, transaction.Witness{}) - require.NoError(t, chain.VerifyTx(tx2)) - - // check that we don't add unexpected extra GAS - tx3 := completeTx(t) - tx3.NetworkFee -= extraFee + 1 - require.NoError(t, acc0.SignTx(testchain.Network(), tx3)) - tx3.Scripts = append(tx3.Scripts, transaction.Witness{}) - require.Error(t, chain.VerifyTx(tx3)) + t.Run("with extra fee", func(t *testing.T) { + // check that calculated network fee with extra value is enough + check(t, extraFee) + }) + t.Run("without extra fee", func(t *testing.T) { + // check that calculated network fee without extra value is enough + check(t, 0) + }) + t.Run("exactFee-1", func(t *testing.T) { + // check that we don't add unexpected extra GAS + check(t, -1) + }) }) t.Run("Invalid", func(t *testing.T) { tx := newTx(t)